implement delta update for erc20
This commit is contained in:
parent
7f32cb5d2f
commit
9064c90b72
|
@ -32,7 +32,7 @@ static app_err_t updater_database_update(uint8_t* data, size_t len) {
|
||||||
return ERR_DATA;
|
return ERR_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eth_db_update((fs_entry_t *) data, len - SIG_LEN) != ERR_OK) {
|
if (eth_db_update(data, len - SIG_LEN) != ERR_OK) {
|
||||||
ui_info(LSTR(INFO_ERROR_TITLE), LSTR(INFO_DB_UPDATE_ERROR), 1);
|
ui_info(LSTR(INFO_ERROR_TITLE), LSTR(INFO_DB_UPDATE_ERROR), 1);
|
||||||
return ERR_DATA;
|
return ERR_DATA;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,7 +11,8 @@ typedef enum {
|
||||||
ERR_HW,
|
ERR_HW,
|
||||||
ERR_UNSUPPORTED,
|
ERR_UNSUPPORTED,
|
||||||
ERR_NEED_MORE_DATA,
|
ERR_NEED_MORE_DATA,
|
||||||
ERR_FULL
|
ERR_FULL,
|
||||||
|
ERR_VERSION
|
||||||
} app_err_t;
|
} app_err_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define FS_CHAIN_MAGIC 0x4348
|
#define FS_CHAIN_MAGIC 0x4348
|
||||||
#define FS_ERC20_MAGIC 0x3020
|
#define FS_ERC20_MAGIC 0x3020
|
||||||
#define FS_VERSION_MAGIC 0x4532
|
#define FS_VERSION_MAGIC 0x4532
|
||||||
|
#define FS_DELTA_MAGIC 0x444c
|
||||||
|
|
||||||
#define ERC20_NET_LEN 24
|
#define ERC20_NET_LEN 24
|
||||||
|
|
||||||
|
@ -24,6 +25,20 @@ struct __attribute__((packed)) version_desc {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) delta_desc {
|
||||||
|
uint16_t magic;
|
||||||
|
uint32_t old_version;
|
||||||
|
uint16_t erase_chain_len;
|
||||||
|
uint16_t erase_token_len;
|
||||||
|
uint8_t data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct delta_erase_ctx {
|
||||||
|
uint8_t* erase_chain;
|
||||||
|
uint8_t* erase_token;
|
||||||
|
uint16_t erase_chain_len;
|
||||||
|
uint16_t erase_token_len;
|
||||||
|
};
|
||||||
|
|
||||||
fs_action_t _eth_db_match_chain(void* ctx, fs_entry_t* entry) {
|
fs_action_t _eth_db_match_chain(void* ctx, fs_entry_t* entry) {
|
||||||
if (entry->magic != FS_CHAIN_MAGIC) {
|
if (entry->magic != FS_CHAIN_MAGIC) {
|
||||||
|
@ -66,6 +81,57 @@ fs_action_t _eth_db_match_all(void* ctx, fs_entry_t* entry) {
|
||||||
return ((entry->magic == FS_CHAIN_MAGIC) || (entry->magic == FS_ERC20_MAGIC) || (entry->magic == FS_VERSION_MAGIC)) ? FS_REJECT : FS_ACCEPT;
|
return ((entry->magic == FS_CHAIN_MAGIC) || (entry->magic == FS_ERC20_MAGIC) || (entry->magic == FS_VERSION_MAGIC)) ? FS_REJECT : FS_ACCEPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline fs_action_t _eth_db_match_erase_chain(struct delta_erase_ctx* ctx, struct chain_raw_desc* entry) {
|
||||||
|
for (int i = 0; i < ctx->erase_chain_len; i += 4) {
|
||||||
|
if (!memcmp(&entry->chain_id, &ctx->erase_chain[i], 4)) {
|
||||||
|
return FS_REJECT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline fs_action_t _eth_db_match_erase_token(struct delta_erase_ctx* ctx, struct erc20_raw_desc* entry) {
|
||||||
|
uint8_t* ticker = entry->data + (entry->net_count * ERC20_NET_LEN) + 1;
|
||||||
|
size_t off = 0;
|
||||||
|
|
||||||
|
while (off < ctx->erase_token_len) {
|
||||||
|
size_t ticker_off = 0;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
if (ticker[ticker_off] != ctx->erase_token[off]) {
|
||||||
|
while(ctx->erase_token[off++] != '\0') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ticker[ticker_off] == '\0') {
|
||||||
|
return FS_REJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ticker_off++;
|
||||||
|
off++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FS_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs_action_t _eth_db_match_delta(void* ctx, fs_entry_t* entry) {
|
||||||
|
switch(entry->magic) {
|
||||||
|
case FS_VERSION_MAGIC:
|
||||||
|
return FS_REJECT;
|
||||||
|
case FS_CHAIN_MAGIC:
|
||||||
|
return _eth_db_match_erase_chain((struct delta_erase_ctx*) ctx, (struct chain_raw_desc*) entry);
|
||||||
|
case FS_ERC20_MAGIC:
|
||||||
|
return _eth_db_match_erase_token((struct delta_erase_ctx*) ctx, (struct erc20_raw_desc*) entry);
|
||||||
|
default:
|
||||||
|
return FS_ACCEPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app_err_t eth_db_lookup_chain(chain_desc_t* chain) {
|
app_err_t eth_db_lookup_chain(chain_desc_t* chain) {
|
||||||
struct chain_raw_desc* chain_data = (struct chain_raw_desc*) fs_find(_eth_db_match_chain, chain);
|
struct chain_raw_desc* chain_data = (struct chain_raw_desc*) fs_find(_eth_db_match_chain, chain);
|
||||||
|
|
||||||
|
@ -106,11 +172,10 @@ app_err_t eth_db_lookup_version(uint32_t* version) {
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
app_err_t eth_db_update(fs_entry_t* entries, size_t len) {
|
static app_err_t eth_full_db_rewrite(fs_entry_t* entries, size_t len) {
|
||||||
app_err_t err = fs_erase_all(_eth_db_match_all, NULL);
|
app_err_t err = fs_erase_all(_eth_db_match_all, NULL);
|
||||||
|
|
||||||
// since our matcher doesn't know when it has reached
|
// since our matcher doesn't know when it has reached completion, if everything went OK the error code
|
||||||
// completion, if everything went OK the error code
|
|
||||||
// will be ERR_DATA on success.
|
// will be ERR_DATA on success.
|
||||||
if (err != ERR_DATA) {
|
if (err != ERR_DATA) {
|
||||||
return err;
|
return err;
|
||||||
|
@ -118,3 +183,56 @@ app_err_t eth_db_update(fs_entry_t* entries, size_t len) {
|
||||||
|
|
||||||
return fs_write(entries, len);
|
return fs_write(entries, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static app_err_t eth_delta_db_update(struct delta_desc* delta, size_t len) {
|
||||||
|
uint32_t version;
|
||||||
|
if (eth_db_lookup_version(&version) != ERR_OK) {
|
||||||
|
return ERR_HW;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delta->old_version != version) {
|
||||||
|
return ERR_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct delta_erase_ctx erase_ctx = {
|
||||||
|
.erase_chain = &delta->data[0],
|
||||||
|
.erase_token = &delta->data[delta->erase_chain_len],
|
||||||
|
.erase_chain_len = delta->erase_chain_len,
|
||||||
|
.erase_token_len = delta->erase_token_len
|
||||||
|
};
|
||||||
|
|
||||||
|
fs_entry_t* entries = (fs_entry_t*) &delta->data[delta->erase_chain_len + delta->erase_token_len];
|
||||||
|
|
||||||
|
size_t off = sizeof(struct delta_desc) + delta->erase_chain_len + delta->erase_token_len;
|
||||||
|
|
||||||
|
if (off > len) {
|
||||||
|
return ERR_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
app_err_t err = fs_erase_all(_eth_db_match_delta, &erase_ctx);
|
||||||
|
|
||||||
|
// since our matcher doesn't know when it has reached completion, if everything went OK the error code
|
||||||
|
// will be ERR_DATA on success. This could be optimized if noticeable delays are observed.
|
||||||
|
if (err != ERR_DATA) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fs_write(entries, (len - off));
|
||||||
|
}
|
||||||
|
|
||||||
|
app_err_t eth_db_update(uint8_t* data, size_t len) {
|
||||||
|
if (len < 1) {
|
||||||
|
return ERR_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t magic = data[0] | (data[1] << 8);
|
||||||
|
|
||||||
|
switch(magic) {
|
||||||
|
case FS_VERSION_MAGIC:
|
||||||
|
return eth_full_db_rewrite((fs_entry_t*) data, len);
|
||||||
|
case FS_DELTA_MAGIC:
|
||||||
|
return eth_delta_db_update((struct delta_desc*) data, len);
|
||||||
|
default:
|
||||||
|
return ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,6 @@ typedef struct {
|
||||||
app_err_t eth_db_lookup_chain(chain_desc_t* chain);
|
app_err_t eth_db_lookup_chain(chain_desc_t* chain);
|
||||||
app_err_t eth_db_lookup_erc20(erc20_desc_t* erc20);
|
app_err_t eth_db_lookup_erc20(erc20_desc_t* erc20);
|
||||||
app_err_t eth_db_lookup_version(uint32_t* version);
|
app_err_t eth_db_lookup_version(uint32_t* version);
|
||||||
app_err_t eth_db_update(fs_entry_t* entries, size_t len);
|
app_err_t eth_db_update(uint8_t* data, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue