From d08d1726f3ada663f83de0ec3cbd7472b35b286c Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Mon, 6 Apr 2020 11:06:13 +0400 Subject: [PATCH 01/26] add nanopb to project, add test code --- Makefile | 2 +- src/ui/nanopb/pb.h | 830 +++++++++++++++++ src/ui/nanopb/pb_common.c | 332 +++++++ src/ui/nanopb/pb_common.h | 45 + src/ui/nanopb/pb_decode.c | 1735 ++++++++++++++++++++++++++++++++++++ src/ui/nanopb/pb_decode.h | 193 ++++ src/ui/nanopb/pb_encode.c | 958 ++++++++++++++++++++ src/ui/nanopb/pb_encode.h | 185 ++++ src/ui/nanopb/simple.pb.c | 12 + src/ui/nanopb/simple.pb.h | 47 + src/ui/nanopb/simple.proto | 9 + src/ui/ui.c | 72 +- 12 files changed, 4411 insertions(+), 9 deletions(-) create mode 100644 src/ui/nanopb/pb.h create mode 100644 src/ui/nanopb/pb_common.c create mode 100644 src/ui/nanopb/pb_common.h create mode 100644 src/ui/nanopb/pb_decode.c create mode 100644 src/ui/nanopb/pb_decode.h create mode 100644 src/ui/nanopb/pb_encode.c create mode 100644 src/ui/nanopb/pb_encode.h create mode 100644 src/ui/nanopb/simple.pb.c create mode 100644 src/ui/nanopb/simple.pb.h create mode 100644 src/ui/nanopb/simple.proto diff --git a/Makefile b/Makefile index 211cebb8..462224d8 100755 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 0 +DEBUG = 1 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) diff --git a/src/ui/nanopb/pb.h b/src/ui/nanopb/pb.h new file mode 100644 index 00000000..09c25261 --- /dev/null +++ b/src/ui/nanopb/pb.h @@ -0,0 +1,830 @@ +/* Common parts of the nanopb library. Most of these are quite low-level + * stuff. For the high-level interface, see pb_encode.h and pb_decode.h. + */ + +#ifndef PB_H_INCLUDED +#define PB_H_INCLUDED + +/***************************************************************** + * Nanopb compilation time options. You can change these here by * + * uncommenting the lines, or on the compiler command line. * + *****************************************************************/ + +/* Enable support for dynamically allocated fields */ +/* #define PB_ENABLE_MALLOC 1 */ + +/* Define this if your CPU / compiler combination does not support + * unaligned memory access to packed structures. */ +/* #define PB_NO_PACKED_STRUCTS 1 */ + +/* Increase the number of required fields that are tracked. + * A compiler warning will tell if you need this. */ +/* #define PB_MAX_REQUIRED_FIELDS 256 */ + +/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ +/* #define PB_FIELD_32BIT 1 */ + +/* Disable support for error messages in order to save some code space. */ +/* #define PB_NO_ERRMSG 1 */ + +/* Disable support for custom streams (support only memory buffers). */ +/* #define PB_BUFFER_ONLY 1 */ + +/* Disable support for 64-bit datatypes, for compilers without int64_t + or to save some code space. */ +/* #define PB_WITHOUT_64BIT 1 */ + +/* Don't encode scalar arrays as packed. This is only to be used when + * the decoder on the receiving side cannot process packed scalar arrays. + * Such example is older protobuf.js. */ +/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */ + +/* Enable conversion of doubles to floats for platforms that do not + * support 64-bit doubles. Most commonly AVR. */ +/* #define PB_CONVERT_DOUBLE_FLOAT 1 */ + +/* Check whether incoming strings are valid UTF-8 sequences. Slows down + * the string processing slightly and slightly increases code size. */ +/* #define PB_VALIDATE_UTF8 1 */ + +/****************************************************************** + * You usually don't need to change anything below this line. * + * Feel free to look around and use the defined macros, though. * + ******************************************************************/ + + +/* Version of the nanopb library. Just in case you want to check it in + * your own program. */ +#define NANOPB_VERSION nanopb-0.4.2-dev + +/* Include all the system headers needed by nanopb. You will need the + * definitions of the following: + * - strlen, memcpy, memset functions + * - [u]int_least8_t, uint_fast8_t, [u]int_least16_t, [u]int32_t, [u]int64_t + * - size_t + * - bool + * + * If you don't have the standard header files, you can instead provide + * a custom header that defines or includes all this. In that case, + * define PB_SYSTEM_HEADER to the path of this file. + */ +#ifdef PB_SYSTEM_HEADER +#include PB_SYSTEM_HEADER +#else +#include +#include +#include +#include +#include + +#ifdef PB_ENABLE_MALLOC +#include +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macro for defining packed structures (compiler dependent). + * This just reduces memory requirements, but is not required. + */ +#if defined(PB_NO_PACKED_STRUCTS) + /* Disable struct packing */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#elif defined(__GNUC__) || defined(__clang__) + /* For GCC and clang */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed __attribute__((packed)) +#elif defined(__ICCARM__) || defined(__CC_ARM) + /* For IAR ARM and Keil MDK-ARM compilers */ +# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +# define pb_packed +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) + /* For Microsoft Visual C++ */ +# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +# define PB_PACKED_STRUCT_END __pragma(pack(pop)) +# define pb_packed +#else + /* Unknown compiler */ +# define PB_PACKED_STRUCT_START +# define PB_PACKED_STRUCT_END +# define pb_packed +#endif + +/* Handly macro for suppressing unreferenced-parameter compiler warnings. */ +#ifndef PB_UNUSED +#define PB_UNUSED(x) (void)(x) +#endif + +/* Harvard-architecture processors may need special attributes for storing + * field information in program memory. */ +#ifndef PB_PROGMEM +#ifdef __AVR__ +#include +#define PB_PROGMEM PROGMEM +#define PB_PROGMEM_READU32(x) pgm_read_dword(&x) +#else +#define PB_PROGMEM +#define PB_PROGMEM_READU32(x) (x) +#endif +#endif + +/* Compile-time assertion, used for checking compatible compilation options. + * If this does not work properly on your compiler, use + * #define PB_NO_STATIC_ASSERT to disable it. + * + * But before doing that, check carefully the error message / place where it + * comes from to see if the error has a real cause. Unfortunately the error + * message is not always very clear to read, but you can see the reason better + * in the place where the PB_STATIC_ASSERT macro was called. + */ +#ifndef PB_NO_STATIC_ASSERT +# ifndef PB_STATIC_ASSERT +# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + /* C11 standard _Static_assert mechanism */ +# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG); +# else + /* Classic negative-size-array static assert mechanism */ +# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER +# endif +# endif +#else + /* Static asserts disabled by PB_NO_STATIC_ASSERT */ +# define PB_STATIC_ASSERT(COND,MSG) +#endif + +/* Number of required fields to keep track of. */ +#ifndef PB_MAX_REQUIRED_FIELDS +#define PB_MAX_REQUIRED_FIELDS 64 +#endif + +#if PB_MAX_REQUIRED_FIELDS < 64 +#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). +#endif + +#ifdef PB_WITHOUT_64BIT +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Cannot use doubles without 64-bit types */ +#undef PB_CONVERT_DOUBLE_FLOAT +#endif +#endif + +/* List of possible field types. These are used in the autogenerated code. + * Least-significant 4 bits tell the scalar type + * Most-significant 4 bits specify repeated/required/packed etc. + */ + +typedef uint_least8_t pb_type_t; + +/**** Field data types ****/ + +/* Numeric types */ +#define PB_LTYPE_BOOL 0x00U /* bool */ +#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */ + +/* Marker for last packable field type. */ +#define PB_LTYPE_LAST_PACKABLE 0x05U + +/* Byte array with pre-allocated buffer. + * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ +#define PB_LTYPE_BYTES 0x06U + +/* String with pre-allocated buffer. + * data_size is the maximum length. */ +#define PB_LTYPE_STRING 0x07U + +/* Submessage + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMESSAGE 0x08U + +/* Submessage with pre-decoding callback + * The pre-decoding callback is stored as pb_callback_t right before pSize. + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMSG_W_CB 0x09U + +/* Extension pseudo-field + * The field contains a pointer to pb_extension_t */ +#define PB_LTYPE_EXTENSION 0x0AU + +/* Byte array with inline, pre-allocated byffer. + * data_size is the length of the inline, allocated buffer. + * This differs from PB_LTYPE_BYTES by defining the element as + * pb_byte_t[data_size] rather than pb_bytes_array_t. */ +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU + +/* Number of declared LTYPES */ +#define PB_LTYPES_COUNT 0x0CU +#define PB_LTYPE_MASK 0x0FU + +/**** Field repetition rules ****/ + +#define PB_HTYPE_REQUIRED 0x00U +#define PB_HTYPE_OPTIONAL 0x10U +#define PB_HTYPE_SINGULAR 0x10U +#define PB_HTYPE_REPEATED 0x20U +#define PB_HTYPE_FIXARRAY 0x20U +#define PB_HTYPE_ONEOF 0x30U +#define PB_HTYPE_MASK 0x30U + +/**** Field allocation types ****/ + +#define PB_ATYPE_STATIC 0x00U +#define PB_ATYPE_POINTER 0x80U +#define PB_ATYPE_CALLBACK 0x40U +#define PB_ATYPE_MASK 0xC0U + +#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) +#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \ + PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB) + +/* Data type used for storing sizes of struct fields + * and array counts. + */ +#if defined(PB_FIELD_32BIT) + typedef uint32_t pb_size_t; + typedef int32_t pb_ssize_t; +#else + typedef uint_least16_t pb_size_t; + typedef int_least16_t pb_ssize_t; +#endif +#define PB_SIZE_MAX ((pb_size_t)-1) + +/* Data type for storing encoded data and other byte streams. + * This typedef exists to support platforms where uint8_t does not exist. + * You can regard it as equivalent on uint8_t on other platforms. + */ +typedef uint_least8_t pb_byte_t; + +/* Forward declaration of struct types */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_field_iter_s pb_field_iter_t; + +/* This structure is used in auto-generated constants + * to specify struct fields. + */ +PB_PACKED_STRUCT_START +typedef struct pb_msgdesc_s pb_msgdesc_t; +struct pb_msgdesc_s { + pb_size_t field_count; + const uint32_t *field_info; + const pb_msgdesc_t * const * submsg_info; + const pb_byte_t *default_value; + + bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field); +} pb_packed; +PB_PACKED_STRUCT_END + +/* Iterator for message descriptor */ +struct pb_field_iter_s { + const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */ + void *message; /* Pointer to start of the structure */ + + pb_size_t index; /* Index of the field */ + pb_size_t field_info_index; /* Index to descriptor->field_info array */ + pb_size_t required_field_index; /* Index that counts only the required fields */ + pb_size_t submessage_index; /* Index that counts only submessages */ + + pb_size_t tag; /* Tag of current field */ + pb_size_t data_size; /* sizeof() of a single item */ + pb_size_t array_size; /* Number of array entries */ + pb_type_t type; /* Type of current field */ + + void *pField; /* Pointer to current field in struct */ + void *pData; /* Pointer to current data contents. Different than pField for arrays and pointers. */ + void *pSize; /* Pointer to count/has field */ + + const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */ +}; + +/* For compatibility with legacy code */ +typedef pb_field_iter_t pb_field_t; + +/* Make sure that the standard integer types are of the expected sizes. + * Otherwise fixed32/fixed64 fields can break. + * + * If you get errors here, it probably means that your stdint.h is not + * correct for your platform. + */ +#ifndef PB_WITHOUT_64BIT +PB_STATIC_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t), INT64_T_WRONG_SIZE) +PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) +#endif + +/* This structure is used for 'bytes' arrays. + * It has the number of bytes in the beginning, and after that an array. + * Note that actual structs used will have a different length of bytes array. + */ +#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) + +struct pb_bytes_array_s { + pb_size_t size; + pb_byte_t bytes[1]; +}; +typedef struct pb_bytes_array_s pb_bytes_array_t; + +/* This structure is used for giving the callback function. + * It is stored in the message structure and filled in by the method that + * calls pb_decode. + * + * The decoding callback will be given a limited-length stream + * If the wire type was string, the length is the length of the string. + * If the wire type was a varint/fixed32/fixed64, the length is the length + * of the actual value. + * The function may be called multiple times (especially for repeated types, + * but also otherwise if the message happens to contain the field multiple + * times.) + * + * The encoding callback will receive the actual output stream. + * It should write all the data in one call, including the field tag and + * wire type. It can write multiple fields. + * + * The callback can be null if you want to skip a field. + */ +typedef struct pb_callback_s pb_callback_t; +struct pb_callback_s { + /* Callback functions receive a pointer to the arg field. + * You can access the value of the field as *arg, and modify it if needed. + */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); + } funcs; + + /* Free arg for use by callback */ + void *arg; +}; + +extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field); + +/* Wire types. Library user needs these only in encoder callbacks. */ +typedef enum { + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 +} pb_wire_type_t; + +/* Structure for defining the handling of unknown/extension fields. + * Usually the pb_extension_type_t structure is automatically generated, + * while the pb_extension_t structure is created by the user. However, + * if you want to catch all unknown fields, you can also create a custom + * pb_extension_type_t with your own callback. + */ +typedef struct pb_extension_type_s pb_extension_type_t; +typedef struct pb_extension_s pb_extension_t; +struct pb_extension_type_s { + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, + uint32_t tag, pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; +}; + +struct pb_extension_s { + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; +}; + +#define pb_extension_init_zero {NULL,NULL,NULL,false} + +/* Memory allocation functions to use. You can define pb_realloc and + * pb_free to custom functions if you want. */ +#ifdef PB_ENABLE_MALLOC +# ifndef pb_realloc +# define pb_realloc(ptr, size) realloc(ptr, size) +# endif +# ifndef pb_free +# define pb_free(ptr) free(ptr) +# endif +#endif + +/* This is used to inform about need to regenerate .pb.h/.pb.c files. */ +#define PB_PROTO_HEADER_VERSION 40 + +/* These macros are used to declare pb_field_t's in the constant array. */ +/* Size of a structure member, in bytes. */ +#define pb_membersize(st, m) (sizeof ((st*)0)->m) +/* Number of entries in an array. */ +#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) +/* Delta from start of one member to the start of another member. */ +#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) + +/* Force expansion of macro value */ +#define PB_EXPAND(x) x + +/* Binding of a message field set into a specific structure */ +#define PB_BIND(msgname, structname, width) \ + const uint32_t structname ## _field_info[] PB_PROGMEM = \ + { \ + msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \ + 0 \ + }; \ + const pb_msgdesc_t* const structname ## _submsg_info[] = \ + { \ + msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \ + NULL \ + }; \ + const pb_msgdesc_t structname ## _msg = \ + { \ + 0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \ + structname ## _field_info, \ + structname ## _submsg_info, \ + msgname ## _DEFAULT, \ + msgname ## _CALLBACK, \ + }; \ + msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname) + +#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1 + +#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(1, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(2, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(4, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(8, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(1, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(2, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(4, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(8, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag) \ + PB_FIELDINFO_ASSERT_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ + PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \ + PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \ + PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \ + PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname)) + +#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) +#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) +#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) +#define PB_DATA_OFFSET_REQUIRED(structname, fieldname) offsetof(structname, fieldname) +#define PB_DATA_OFFSET_SINGULAR(structname, fieldname) offsetof(structname, fieldname) +#define PB_DATA_OFFSET_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_OFFSET_OPTIONAL(structname, fieldname) offsetof(structname, fieldname) +#define PB_DATA_OFFSET_REPEATED(structname, fieldname) offsetof(structname, fieldname) +#define PB_DATA_OFFSET_FIXARRAY(structname, fieldname) offsetof(structname, fieldname) + +#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SIZE_OFFSET_ ## htype(structname, fieldname) +#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SIZE_OFFSET_PTR_ ## htype(structname, fieldname) +#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SIZE_OFFSET_CB_ ## htype(structname, fieldname) +#define PB_SIZE_OFFSET_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname)) +#define PB_SIZE_OFFSET_ONEOF2(structname, fullname, unionname) PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) +#define PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname) +#define PB_SIZE_OFFSET_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname) +#define PB_SIZE_OFFSET_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count) +#define PB_SIZE_OFFSET_FIXARRAY(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname) +#define PB_SIZE_OFFSET_PTR_OPTIONAL(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_REPEATED(structname, fieldname) PB_SIZE_OFFSET_REPEATED(structname, fieldname) +#define PB_SIZE_OFFSET_PTR_FIXARRAY(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname) +#define PB_SIZE_OFFSET_CB_OPTIONAL(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_REPEATED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_FIXARRAY(structname, fieldname) 0 + +#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_ARRAY_SIZE_ ## htype(structname, fieldname) +#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_ARRAY_SIZE_PTR_ ## htype(structname, fieldname) +#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1 +#define PB_ARRAY_SIZE_REQUIRED(structname, fieldname) 1 +#define PB_ARRAY_SIZE_SINGULAR(structname, fieldname) 1 +#define PB_ARRAY_SIZE_OPTIONAL(structname, fieldname) 1 +#define PB_ARRAY_SIZE_ONEOF(structname, fieldname) 1 +#define PB_ARRAY_SIZE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname) +#define PB_ARRAY_SIZE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname) +#define PB_ARRAY_SIZE_PTR_REQUIRED(structname, fieldname) 1 +#define PB_ARRAY_SIZE_PTR_SINGULAR(structname, fieldname) 1 +#define PB_ARRAY_SIZE_PTR_OPTIONAL(structname, fieldname) 1 +#define PB_ARRAY_SIZE_PTR_ONEOF(structname, fieldname) 1 +#define PB_ARRAY_SIZE_PTR_REPEATED(structname, fieldname) 1 +#define PB_ARRAY_SIZE_PTR_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0]) + +#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DATA_SIZE_ ## htype(structname, fieldname) +#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DATA_SIZE_PTR_ ## htype(structname, fieldname) +#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DATA_SIZE_CB_ ## htype(structname, fieldname) +#define PB_DATA_SIZE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_SIZE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0]) +#define PB_DATA_SIZE_PTR_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0]) +#define PB_DATA_SIZE_CB_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_SIZE_CB_REPEATED(structname, fieldname) pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname) + +#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple) +#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname +#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername +#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname + +#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \ + PB_SUBMSG_INFO_ ## htype(ltype, structname, fieldname) + +#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname)) +#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) +#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE) +#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) +#define PB_SUBMSG_INFO_BOOL(t) +#define PB_SUBMSG_INFO_BYTES(t) +#define PB_SUBMSG_INFO_DOUBLE(t) +#define PB_SUBMSG_INFO_ENUM(t) +#define PB_SUBMSG_INFO_UENUM(t) +#define PB_SUBMSG_INFO_FIXED32(t) +#define PB_SUBMSG_INFO_FIXED64(t) +#define PB_SUBMSG_INFO_FLOAT(t) +#define PB_SUBMSG_INFO_INT32(t) +#define PB_SUBMSG_INFO_INT64(t) +#define PB_SUBMSG_INFO_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SUBMSG_INFO_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SUBMSG_INFO_SFIXED32(t) +#define PB_SUBMSG_INFO_SFIXED64(t) +#define PB_SUBMSG_INFO_SINT32(t) +#define PB_SUBMSG_INFO_SINT64(t) +#define PB_SUBMSG_INFO_STRING(t) +#define PB_SUBMSG_INFO_UINT32(t) +#define PB_SUBMSG_INFO_UINT64(t) +#define PB_SUBMSG_INFO_EXTENSION(t) +#define PB_SUBMSG_INFO_FIXED_LENGTH_BYTES(t) +#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg), + +/* The field descriptors use a variable width format, with width of either + * 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always + * encode the descriptor size, 6 lowest bits of field tag number, and 8 bits + * of the field type. + * + * Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words. + * + * Formats, listed starting with the least significant bit of the first word. + * 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size] + * + * 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset] + * [16-bit data_offset] [12-bit data_size] [4-bit tag>>6] + * + * 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * + * 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * [32-bit array_size] + * [32-bit reserved] + * [32-bit reserved] + * [32-bit reserved] + */ + +#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \ + (0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \ + (((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)), + +#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \ + (1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \ + (((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)), + +#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \ + (2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \ + ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), + +#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \ + (3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \ + ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), (array_size), 0, 0, 0, + +/* These assertions verify that the field information fits in the allocated space. + * The generator tries to automatically determine the correct width that can fit all + * data associated with a message. These asserts will fail only if there has been a + * problem in the automatic logic - this may be worth reporting as a bug. As a workaround, + * you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting + * descriptorsize option in .options file. + */ +#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<2GB messages with nanopb anyway. + */ +#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag) + +#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag) +#endif + + +/* Automatic picking of FIELDINFO width: + * Uses width 1 when possible, otherwise resorts to width 2. + * This is used when PB_BIND() is called with "AUTO" as the argument. + * The generator will give explicit size argument when it knows that a message + * structure grows beyond 1-word format limits. + */ +#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FIELDINFO_WIDTH_ ## atype(htype, ltype) +#define PB_FIELDINFO_WIDTH_STATIC(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype) +#define PB_FIELDINFO_WIDTH_POINTER(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype) +#define PB_FIELDINFO_WIDTH_CALLBACK(htype, ltype) 2 +#define PB_FIELDINFO_WIDTH_REQUIRED(ltype) PB_FIELDINFO_WIDTH_ ## ltype +#define PB_FIELDINFO_WIDTH_SINGULAR(ltype) PB_FIELDINFO_WIDTH_ ## ltype +#define PB_FIELDINFO_WIDTH_OPTIONAL(ltype) PB_FIELDINFO_WIDTH_ ## ltype +#define PB_FIELDINFO_WIDTH_ONEOF(ltype) PB_FIELDINFO_WIDTH_ ## ltype +#define PB_FIELDINFO_WIDTH_REPEATED(ltype) 2 +#define PB_FIELDINFO_WIDTH_FIXARRAY(ltype) 2 +#define PB_FIELDINFO_WIDTH_BOOL 1 +#define PB_FIELDINFO_WIDTH_BYTES 2 +#define PB_FIELDINFO_WIDTH_DOUBLE 1 +#define PB_FIELDINFO_WIDTH_ENUM 1 +#define PB_FIELDINFO_WIDTH_UENUM 1 +#define PB_FIELDINFO_WIDTH_FIXED32 1 +#define PB_FIELDINFO_WIDTH_FIXED64 1 +#define PB_FIELDINFO_WIDTH_FLOAT 1 +#define PB_FIELDINFO_WIDTH_INT32 1 +#define PB_FIELDINFO_WIDTH_INT64 1 +#define PB_FIELDINFO_WIDTH_MESSAGE 2 +#define PB_FIELDINFO_WIDTH_MSG_W_CB 2 +#define PB_FIELDINFO_WIDTH_SFIXED32 1 +#define PB_FIELDINFO_WIDTH_SFIXED64 1 +#define PB_FIELDINFO_WIDTH_SINT32 1 +#define PB_FIELDINFO_WIDTH_SINT64 1 +#define PB_FIELDINFO_WIDTH_STRING 2 +#define PB_FIELDINFO_WIDTH_UINT32 1 +#define PB_FIELDINFO_WIDTH_UINT64 1 +#define PB_FIELDINFO_WIDTH_EXTENSION 1 +#define PB_FIELDINFO_WIDTH_FIXED_LENGTH_BYTES 2 + +/* The mapping from protobuf types to LTYPEs is done using these macros. */ +#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES + +/* These macros are used for giving out error messages. + * They are mostly a debugging aid; the main error information + * is the true/false return value from functions. + * Some code space can be saved by disabling the error + * messages if not used. + * + * PB_SET_ERROR() sets the error message if none has been set yet. + * msg must be a constant string literal. + * PB_GET_ERROR() always returns a pointer to a string. + * PB_RETURN_ERROR() sets the error and returns false from current + * function. + */ +#ifdef PB_NO_ERRMSG +#define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) +#define PB_GET_ERROR(stream) "(errmsg disabled)" +#else +#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") +#endif + +#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define PB_CONSTEXPR constexpr +#else // __cplusplus >= 201103L +#define PB_CONSTEXPR +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR inline constexpr +#else // __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR PB_CONSTEXPR +#endif // __cplusplus >= 201703L + +namespace nanopb { +// Each type will be partially specialized by the generator. +template struct MessageDescriptor; +} // namespace nanopb +#endif /* __cplusplus */ + +#endif + diff --git a/src/ui/nanopb/pb_common.c b/src/ui/nanopb/pb_common.c new file mode 100644 index 00000000..64eebe39 --- /dev/null +++ b/src/ui/nanopb/pb_common.c @@ -0,0 +1,332 @@ +/* pb_common.c: Common support functions for pb_encode.c and pb_decode.c. + * + * 2014 Petteri Aimonen + */ + +#include "pb_common.h" + +static bool load_descriptor_values(pb_field_iter_t *iter) +{ + uint32_t word0; + uint32_t data_offset; + uint_least8_t format; + int_least8_t size_offset; + if (iter->index >= iter->descriptor->field_count) + return false; + word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + format = word0 & 3; + iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); + iter->type = (pb_type_t)((word0 >> 8) & 0xFF); + + if (format == 0) + { + /* 1-word format */ + iter->array_size = 1; + size_offset = (int_least8_t)((word0 >> 24) & 0x0F); + data_offset = (word0 >> 16) & 0xFF; + iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); + } + else if (format == 1) + { + /* 2-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + + iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 28) << 6)); + size_offset = (int_least8_t)((word0 >> 28) & 0x0F); + data_offset = word1 & 0xFFFF; + iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); + } + else if (format == 2) + { + /* 4-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); + + iter->array_size = (pb_size_t)(word0 >> 16); + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); + size_offset = (int_least8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + } + else + { + /* 8-word format */ + uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); + uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]); + + iter->array_size = (pb_size_t)word4; + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); + size_offset = (int_least8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + } + + iter->pField = (char*)iter->message + data_offset; + + if (size_offset) + { + iter->pSize = (char*)iter->pField - size_offset; + } + else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && + (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || + PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) + { + /* Fixed count array */ + iter->pSize = &iter->array_size; + } + else + { + iter->pSize = NULL; + } + + if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) + { + iter->pData = *(void**)iter->pField; + } + else + { + iter->pData = iter->pField; + } + + if (PB_LTYPE_IS_SUBMSG(iter->type)) + { + iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index]; + } + else + { + iter->submsg_desc = NULL; + } + + return true; +} + +static void advance_iterator(pb_field_iter_t *iter) +{ + iter->index++; + + if (iter->index >= iter->descriptor->field_count) + { + /* Restart */ + iter->index = 0; + iter->field_info_index = 0; + iter->submessage_index = 0; + iter->required_field_index = 0; + } + else + { + /* Increment indexes based on previous field type. + * All field info formats have the following fields: + * - lowest 2 bits tell the amount of words in the descriptor (2^n words) + * - bits 2..7 give the lowest bits of tag number. + * - bits 8..15 give the field type. + */ + uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; + pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); + + iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len); + + if (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED) + { + iter->required_field_index++; + } + + if (PB_LTYPE_IS_SUBMSG(prev_type)) + { + iter->submessage_index++; + } + } +} + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message) +{ + memset(iter, 0, sizeof(*iter)); + iter->descriptor = desc; + iter->message = message; + return load_descriptor_values(iter); +} + +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg; + bool status; + + uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); + if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + status = pb_field_iter_begin(iter, msg, &extension->dest); + } + else + { + status = pb_field_iter_begin(iter, msg, extension->dest); + } + + iter->pSize = &extension->found; + return status; +} + +bool pb_field_iter_next(pb_field_iter_t *iter) +{ + advance_iterator(iter); + (void)load_descriptor_values(iter); + return iter->index != 0; +} + +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) +{ + if (iter->tag == tag) + { + return true; /* Nothing to do, correct field already. */ + } + else + { + pb_size_t start = iter->index; + uint32_t fieldinfo; + + do + { + /* Advance iterator but don't load values yet */ + advance_iterator(iter); + + /* Do fast check for tag number match */ + fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); + + if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) + { + /* Good candidate, check further */ + (void)load_descriptor_values(iter); + + if (iter->tag == tag && + PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) + { + /* Found it */ + return true; + } + } + } while (iter->index != start); + + /* Searched all the way back to start, and found nothing. */ + (void)load_descriptor_values(iter); + return false; + } +} + +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. The cast is done using union + * to avoid spurious compiler warnings. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message) +{ + return pb_field_iter_begin(iter, desc, pb_const_cast(message)); +} + +bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension) +{ + return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension)); +} + +bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) +{ + if (field->data_size == sizeof(pb_callback_t)) + { + pb_callback_t *pCallback = (pb_callback_t*)field->pData; + + if (pCallback != NULL) + { + if (istream != NULL && pCallback->funcs.decode != NULL) + { + return pCallback->funcs.decode(istream, field, &pCallback->arg); + } + + if (ostream != NULL && pCallback->funcs.encode != NULL) + { + return pCallback->funcs.encode(ostream, field, &pCallback->arg); + } + } + } + + return true; /* Success, but didn't do anything */ + +} + +#ifdef PB_VALIDATE_UTF8 + +/* This function checks whether a string is valid UTF-8 text. + * + * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c + * Original copyright: Markus Kuhn 2005-03-30 + * Licensed under "Short code license", which allows use under MIT license or + * any compatible with it. + */ + +bool pb_validate_utf8(const char *str) +{ + const pb_byte_t *s = (const pb_byte_t*)str; + while (*s) + { + if (*s < 0x80) + { + /* 0xxxxxxx */ + s++; + } + else if ((s[0] & 0xe0) == 0xc0) + { + /* 110XXXXx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[0] & 0xfe) == 0xc0) /* overlong? */ + return false; + else + s += 2; + } + else if ((s[0] & 0xf0) == 0xe0) + { + /* 1110XXXX 10Xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ + (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ + (s[0] == 0xef && s[1] == 0xbf && + (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ + return false; + else + s += 3; + } + else if ((s[0] & 0xf8) == 0xf0) + { + /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || + (s[2] & 0xc0) != 0x80 || + (s[3] & 0xc0) != 0x80 || + (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ + (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ + return false; + else + s += 4; + } + else + { + return false; + } + } + + return true; +} + +#endif + diff --git a/src/ui/nanopb/pb_common.h b/src/ui/nanopb/pb_common.h new file mode 100644 index 00000000..47fa2c99 --- /dev/null +++ b/src/ui/nanopb/pb_common.h @@ -0,0 +1,45 @@ +/* pb_common.h: Common support functions for pb_encode.c and pb_decode.c. + * These functions are rarely needed by applications directly. + */ + +#ifndef PB_COMMON_H_INCLUDED +#define PB_COMMON_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initialize the field iterator structure to beginning. + * Returns false if the message type is empty. */ +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message); + +/* Get a field iterator for extension field. */ +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension); + +/* Same as pb_field_iter_begin(), but for const message pointer. + * Note that the pointers in pb_field_iter_t will be non-const but shouldn't + * be written to when using these functions. */ +bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message); +bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension); + +/* Advance the iterator to the next field. + * Returns false when the iterator wraps back to the first field. */ +bool pb_field_iter_next(pb_field_iter_t *iter); + +/* Advance the iterator until it points at a field with the given tag. + * Returns false if no such field exists. */ +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); + +#ifdef PB_VALIDATE_UTF8 +/* Validate UTF-8 text string */ +bool pb_validate_utf8(const char *s); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/src/ui/nanopb/pb_decode.c b/src/ui/nanopb/pb_decode.c new file mode 100644 index 00000000..f936412b --- /dev/null +++ b/src/ui/nanopb/pb_decode.c @@ -0,0 +1,1735 @@ +/* pb_decode.c -- decode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +#include "pb.h" +#include "pb_decode.h" +#include "pb_common.h" + +/************************************** + * Declarations internal to this file * + **************************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); +static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn find_extension_field(pb_field_iter_t *iter); +static bool pb_message_set_to_defaults(pb_field_iter_t *iter); +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_skip_varint(pb_istream_t *stream); +static bool checkreturn pb_skip_string(pb_istream_t *stream); + +#ifdef PB_ENABLE_MALLOC +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field); +static void pb_release_single_field(pb_field_iter_t *field); +#endif + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +typedef struct { + uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32]; +} pb_fields_seen_t; + +/******************************* + * pb_istream_t implementation * + *******************************/ + +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + size_t i; + const pb_byte_t *source = (const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + count; + + if (buf != NULL) + { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + if (count == 0) + return true; + +#ifndef PB_BUFFER_ONLY + if (buf == NULL && stream->callback != buf_read) + { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) + { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } +#endif + + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!buf_read(stream, buf, count)) + return false; +#endif + + stream->bytes_left -= count; + return true; +} + +/* Read a single byte from input stream. buf may not be NULL. + * This is an optimization for the varint decoding. */ +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) +{ + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); + +#ifndef PB_BUFFER_ONLY + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); +#else + *buf = *(const pb_byte_t*)stream->state; + stream->state = (pb_byte_t*)stream->state + 1; +#endif + + stream->bytes_left--; + + return true; +} + +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) +{ + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; +#ifdef PB_BUFFER_ONLY + stream.callback = NULL; +#else + stream.callback = &buf_read; +#endif + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +/******************** + * Helper functions * + ********************/ + +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) +{ + pb_byte_t byte; + uint32_t result; + + if (!pb_readbyte(stream, &byte)) + { + if (stream->bytes_left == 0) + { + if (eof) + { + *eof = true; + } + } + + return false; + } + + if ((byte & 0x80) == 0) + { + /* Quick case, 1 byte value */ + result = byte; + } + else + { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do + { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) + { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ + pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) + { + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + else + { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) + { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; +} + +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) +{ + return pb_decode_varint32_eof(stream, dest, NULL); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) +{ + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do + { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; +} +#endif + +bool checkreturn pb_skip_varint(pb_istream_t *stream) +{ + pb_byte_t byte; + do + { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; +} + +bool checkreturn pb_skip_string(pb_istream_t *stream) +{ + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + if ((size_t)length != length) + { + PB_RETURN_ERROR(stream, "size too large"); + } + + return pb_read(stream, NULL, (size_t)length); +} + +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) +{ + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t) 0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) + { + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; +} + +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) +{ + switch (wire_type) + { + case PB_WT_VARINT: return pb_skip_varint(stream); + case PB_WT_64BIT: return pb_read(stream, NULL, 8); + case PB_WT_STRING: return pb_skip_string(stream); + case PB_WT_32BIT: return pb_read(stream, NULL, 4); + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Read a raw value to buffer, for the purpose of passing it to callback as + * a substream. Size is maximum size on call, and actual size on return. + */ +static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) +{ + size_t max_size = *size; + switch (wire_type) + { + case PB_WT_VARINT: + *size = 0; + do + { + (*size)++; + if (*size > max_size) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_read(stream, buf, 1)) + return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: PB_RETURN_ERROR(stream, "invalid wire_type"); + } +} + +/* Decode string length from stream and return a substream with limited length. + * Remember to close the substream using pb_close_string_substream(). + */ +bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = (size_t)size; + stream->bytes_left -= (size_t)size; + return true; +} + +bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) +{ + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } + + stream->state = substream->state; + +#ifndef PB_NO_ERRMSG + stream->errmsg = substream->errmsg; +#endif + return true; +} + +/************************* + * Decode a single field * + *************************/ + +static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return wire_type == PB_WT_VARINT; + + case PB_LTYPE_FIXED32: + return wire_type == PB_WT_32BIT; + + case PB_LTYPE_FIXED64: + return wire_type == PB_WT_64BIT; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + case PB_LTYPE_FIXED_LENGTH_BYTES: + return wire_type == PB_WT_STRING; + + default: + return false; + } +} + +static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field) +{ + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + return pb_dec_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return pb_dec_varint(stream, field); + + case PB_LTYPE_FIXED32: + case PB_LTYPE_FIXED64: + return pb_dec_fixed(stream, field); + + case PB_LTYPE_BYTES: + return pb_dec_bytes(stream, field); + + case PB_LTYPE_STRING: + return pb_dec_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + return pb_dec_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + return pb_dec_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return decode_basic_field(stream, field); + + case PB_HTYPE_OPTIONAL: + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + if (field->pSize != NULL) + *(bool*)field->pSize = true; + return decode_basic_field(stream, field); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array */ + bool status = true; + pb_istream_t substream; + pb_size_t *size = (pb_size_t*)field->pSize; + field->pData = (char*)field->pField + field->data_size * (*size); + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < field->array_size) + { + if (!decode_basic_field(&substream, field)) + { + status = false; + break; + } + (*size)++; + field->pData = (char*)field->pData + field->data_size; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Repeated field */ + pb_size_t *size = (pb_size_t*)field->pSize; + field->pData = (char*)field->pField + field->data_size * (*size); + + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + if ((*size)++ >= field->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return decode_basic_field(stream, field); + } + + case PB_HTYPE_ONEOF: + *(pb_size_t*)field->pSize = field->tag; + if (PB_LTYPE_IS_SUBMSG(field->type)) + { + /* We memset to zero so that any callbacks are set to NULL. + * This is because the callbacks might otherwise have values + * from some other union field. + * If callbacks are needed inside oneof field, use .proto + * option submsg_callback to have a separate callback function + * that can set the fields before submessage is decoded. + * pb_dec_submessage() will set any default values. */ + memset(field->pData, 0, (size_t)field->data_size); + } + + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + return decode_basic_field(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +#ifdef PB_ENABLE_MALLOC +/* Allocate storage for the field and store the pointer at iter->pData. + * array_size is the number of entries to reserve in an array. + * Zero size is not allowed, use pb_free() for releasing. + */ +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) +{ + void *ptr = *(void**)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + +#ifdef __AVR__ + /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284 + * Realloc to size of 1 byte can cause corruption of the malloc structures. + */ + if (data_size == 1 && array_size == 1) + { + data_size = 2; + } +#endif + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) + { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) + { + PB_RETURN_ERROR(stream, "size too large"); + } + } + } + + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void**)pData = ptr; + return true; +} + +/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) + { + *(void**)pItem = NULL; + } + else if (PB_LTYPE_IS_SUBMSG(field->type)) + { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + pb_field_iter_t submsg_iter; + memset(pItem, 0, field->data_size); + + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, pItem)) + { + (void)pb_message_set_to_defaults(&submsg_iter); + } + } +} +#endif + +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ +#ifndef PB_ENABLE_MALLOC + PB_UNUSED(wire_type); + PB_UNUSED(field); + PB_RETURN_ERROR(stream, "no malloc support"); +#else + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL) + { + /* Duplicate field, have to release the old allocation first. */ + /* FIXME: Does this work correctly for oneofs? */ + pb_release_single_field(field); + } + + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)field->pSize = field->tag; + } + + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) + { + /* pb_dec_string and pb_dec_bytes handle allocation themselves */ + field->pData = field->pField; + return decode_basic_field(stream, field); + } + else + { + if (!allocate_field(stream, field->pField, field->data_size, 1)) + return false; + + field->pData = *(void**)field->pField; + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, field); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING + && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t*)field->pSize; + size_t allocated_size = *size; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) + { + if (*size == PB_SIZE_MAX) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif + status = false; + break; + } + + if ((size_t)*size + 1 > allocated_size) + { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + size_t remain = (substream.bytes_left - 1) / field->data_size + 1; + if (remain < PB_SIZE_MAX - allocated_size) + allocated_size += remain; + else + allocated_size += 1; + + if (!allocate_field(&substream, field->pField, field->data_size, allocated_size)) + { + status = false; + break; + } + } + + /* Decode the array entry */ + field->pData = *(char**)field->pField + field->data_size * (*size); + initialize_pointer_field(field->pData, field); + if (!decode_basic_field(&substream, field)) + { + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } + else + { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t*)field->pSize; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + if (!check_wire_type(wire_type, field)) + PB_RETURN_ERROR(stream, "wrong wire type"); + + if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1))) + return false; + + field->pData = *(char**)field->pField + field->data_size * (*size); + (*size)++; + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, field); + } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +#endif +} + +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ + if (!field->descriptor->field_callback) + return pb_skip_field(stream, wire_type); + + if (wire_type == PB_WT_STRING) + { + pb_istream_t substream; + size_t prev_bytes_left; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + do + { + prev_bytes_left = substream.bytes_left; + if (!field->descriptor->field_callback(&substream, NULL, field)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left > 0 && substream.bytes_left < prev_bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } + else + { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return field->descriptor->field_callback(&substream, NULL, field); + } +} + +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +{ +#ifdef PB_ENABLE_MALLOC + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + if (!pb_release_union_field(stream, field)) + return false; + } +#endif + + switch (PB_ATYPE(field->type)) + { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, field); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, field); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension(&iter, extension)) + PB_RETURN_ERROR(stream, "invalid extension"); + + if (iter.tag != tag) + return true; + + extension->found = true; + return decode_field(stream, wire_type, &iter); +} + +/* Try to decode an unknown field as an extension field. Tries each extension + * decoder in turn, until one of them handles the field or loop ends. */ +static bool checkreturn decode_extension(pb_istream_t *stream, + uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) +{ + pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; + size_t pos = stream->bytes_left; + + while (extension != NULL && pos == stream->bytes_left) + { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/* Step through the iterator until an extension field is found or until all + * entries have been checked. There can be only one extension field per + * message. Returns false if no extension field is found. */ +static bool checkreturn find_extension_field(pb_field_iter_t *iter) +{ + pb_size_t start = iter->index; + + do { + if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->index != start); + + return false; +} + +/* Initialize message fields to default values, recursively */ +static bool pb_field_set_to_default(pb_field_iter_t *field) +{ + pb_type_t type; + type = field->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + pb_extension_t *ext = *(pb_extension_t* const *)field->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) + { + ext->found = false; + if (!pb_message_set_to_defaults(&ext_iter)) + return false; + } + ext = ext->next; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) + { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool*)field->pSize = false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t*)field->pSize = 0; + init_data = false; + } + + if (init_data) + { + if (PB_LTYPE_IS_SUBMSG(field->type)) + { + /* Initialize submessage to defaults */ + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) + { + if (!pb_message_set_to_defaults(&submsg_iter)) + return false; + } + } + else + { + /* Initialize to zeros */ + memset(field->pData, 0, (size_t)field->data_size); + } + } + } + else if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + /* Initialize the pointer to NULL. */ + *(void**)field->pField = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + *(pb_size_t*)field->pSize = 0; + } + } + else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) + { + /* Don't overwrite callback */ + } + + return true; +} + +static bool pb_message_set_to_defaults(pb_field_iter_t *iter) +{ + pb_istream_t defstream = PB_ISTREAM_EMPTY; + uint32_t tag = 0; + pb_wire_type_t wire_type = PB_WT_VARINT; + bool eof; + + if (iter->descriptor->default_value) + { + defstream = pb_istream_from_buffer(iter->descriptor->default_value, (size_t)-1); + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + } + + do + { + if (!pb_field_set_to_default(iter)) + return false; + + if (tag != 0 && iter->tag == tag) + { + /* We have a default value for this field in the defstream */ + if (!decode_field(&defstream, wire_type, iter)) + return false; + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + + if (iter->pSize) + *(bool*)iter->pSize = false; + } + } while (pb_field_iter_next(iter)); + + return true; +} + +/********************* + * Decode all fields * + *********************/ + +static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +{ + uint32_t extension_range_start = 0; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed + * count field. This can only handle _one_ repeated fixed count field that + * is unpacked and unordered among other (non repeated fixed count) fields. + */ + pb_size_t fixed_count_field = PB_SIZE_MAX; + pb_size_t fixed_count_size = 0; + pb_size_t fixed_count_total_size = 0; + + pb_fields_seen_t fields_seen = {{0, 0}}; + const uint32_t allbits = ~(uint32_t)0; + pb_field_iter_t iter; + + if (pb_field_iter_begin(&iter, fields, dest_struct)) + { + if ((flags & PB_DECODE_NOINIT) == 0) + { + if (!pb_message_set_to_defaults(&iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); + } + } + + while (stream->bytes_left) + { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) + { + if (eof) + break; + else + return false; + } + + if (tag == 0) + { + if (flags & PB_DECODE_NULLTERMINATED) + { + break; + } + else + { + PB_RETURN_ERROR(stream, "zero tag"); + } + } + + if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) + { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) + { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.tag; + + if (tag >= extension_range_start) + { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) + { + /* The field was handled */ + continue; + } + } + } + + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; + } + + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED && iter.pSize == &iter.array_size) + { + if (fixed_count_field != iter.index) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. + */ + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + fixed_count_field = iter.index; + fixed_count_size = 0; + fixed_count_total_size = iter.array_size; + } + + iter.pSize = &fixed_count_size; + } + + if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED + && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) + { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen.bitfield[iter.required_field_index >> 5] |= tmp; + } + + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. */ + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) + { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + pb_size_t req_field_count; + pb_type_t last_type; + pb_size_t i; + do { + req_field_count = iter.required_field_index; + last_type = iter.type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) + { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) + { + if (fields_seen.bitfield[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) + { + if (fields_seen.bitfield[req_field_count >> 5] != + (allbits >> (uint_least8_t)(32 - (req_field_count & 31)))) + { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; +} + +bool checkreturn pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +{ + bool status; + + if ((flags & PB_DECODE_DELIMITED) == 0) + { + status = pb_decode_inner(stream, fields, dest_struct, flags); + } + else + { + pb_istream_t substream; + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode_inner(&substream, fields, dest_struct, flags); + + if (!pb_close_string_substream(stream, &substream)) + return false; + } + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +bool checkreturn pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct) +{ + bool status; + + status = pb_decode_inner(stream, fields, dest_struct, 0); + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; +} + +#ifdef PB_ENABLE_MALLOC +/* Given an oneof field, if there has already been a field inside this oneof, + * release it before overwriting with a different one. */ +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field) +{ + pb_field_iter_t old_field = *field; + pb_size_t old_tag = *(pb_size_t*)field->pSize; /* Previous which_ value */ + pb_size_t new_tag = field->tag; /* New which_ value */ + + if (old_tag == 0) + return true; /* Ok, no old data in union */ + + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ + + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(&old_field, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); + + pb_release_single_field(&old_field); + + return true; +} + +static void pb_release_single_field(pb_field_iter_t *field) +{ + pb_type_t type; + type = field->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + if (*(pb_size_t*)field->pSize != field->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) + { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t**)field->pData; + while (ext != NULL) + { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) + { + pb_release_single_field(&ext_iter); + } + ext = ext->next; + } + } + else if (PB_LTYPE_IS_SUBMSG(type) && PB_ATYPE(type) != PB_ATYPE_CALLBACK) + { + /* Release fields in submessage or submsg array */ + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + field->pData = *(void**)field->pField; + } + else + { + field->pData = field->pField; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + count = *(pb_size_t*)field->pSize; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > field->array_size) + { + /* Protect against corrupted _count fields */ + count = field->array_size; + } + } + + if (field->pData) + { + while (count--) + { + pb_release(field->submsg_desc, field->pData); + field->pData = (char*)field->pData + field->data_size; + } + } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) + { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) + { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void***)field->pField; + pb_size_t count = *(pb_size_t*)field->pSize; + while (count--) + { + pb_free(*pItem); + *pItem++ = NULL; + } + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t*)field->pSize = 0; + } + + /* Release main pointer */ + pb_free(*(void**)field->pField); + *(void**)field->pField = NULL; + } +} + +void pb_release(const pb_msgdesc_t *fields, void *dest_struct) +{ + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do + { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); +} +#endif + +/* Field decoders */ + +bool pb_decode_bool(pb_istream_t *stream, bool *dest) +{ + uint32_t value; + if (!pb_decode_varint32(stream, &value)) + return false; + + *(bool*)dest = (value != 0); + return true; +} + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) +{ + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; +} + +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) +{ + union { + uint32_t fixed32; + pb_byte_t bytes[4]; + } u; + + if (!pb_read(stream, u.bytes, 4)) + return false; + +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint32_t*)dest = u.fixed32; +#else + *(uint32_t*)dest = ((uint32_t)u.bytes[0] << 0) | + ((uint32_t)u.bytes[1] << 8) | + ((uint32_t)u.bytes[2] << 16) | + ((uint32_t)u.bytes[3] << 24); +#endif + return true; +} + +#ifndef PB_WITHOUT_64BIT +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) +{ + union { + uint64_t fixed64; + pb_byte_t bytes[8]; + } u; + + if (!pb_read(stream, u.bytes, 8)) + return false; + +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint64_t*)dest = u.fixed64; +#else + *(uint64_t*)dest = ((uint64_t)u.bytes[0] << 0) | + ((uint64_t)u.bytes[1] << 8) | + ((uint64_t)u.bytes[2] << 16) | + ((uint64_t)u.bytes[3] << 24) | + ((uint64_t)u.bytes[4] << 32) | + ((uint64_t)u.bytes[5] << 40) | + ((uint64_t)u.bytes[6] << 48) | + ((uint64_t)u.bytes[7] << 56); +#endif + return true; +} +#endif + +static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field) +{ + return pb_decode_bool(stream, (bool*)field->pData); +} + +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) + { + pb_uint64_t value, clamped; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)field->pData = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)field->pData = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)field->pData = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)field->pData = (uint_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; + } + else + { + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; + + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) + { + if (!pb_decode_svarint(stream, &svalue)) + return false; + } + else + { + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + } + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)field->pData = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)field->pData = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)field->pData = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)field->pData = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; + } +} + +static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field) +{ +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + return pb_decode_double_as_float(stream, (float*)field->pData); + } +#endif + + if (field->data_size == sizeof(uint32_t)) + { + return pb_decode_fixed32(stream, field->pData); + } +#ifndef PB_WITHOUT_64BIT + else if (field->data_size == sizeof(uint64_t)) + { + return pb_decode_fixed64(stream, field->pData); + } +#endif + else + { + PB_RETURN_ERROR(stream, "invalid data_size"); + } +} + +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *dest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (stream->bytes_left < size) + PB_RETURN_ERROR(stream, "end-of-stream"); + + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_bytes_array_t**)field->pData; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + dest = (pb_bytes_array_t*)field->pData; + } + + dest->size = (pb_size_t)size; + return pb_read(stream, dest->bytes, (size_t)size); +} + +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + size_t alloc_size; + pb_byte_t *dest = (pb_byte_t*)field->pData; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size == (uint32_t)-1) + PB_RETURN_ERROR(stream, "size too large"); + + /* Space for null terminator */ + alloc_size = (size_t)(size + 1); + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { +#ifndef PB_ENABLE_MALLOC + PB_RETURN_ERROR(stream, "no malloc support"); +#else + if (stream->bytes_left < size) + PB_RETURN_ERROR(stream, "end-of-stream"); + + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_byte_t**)field->pData; +#endif + } + else + { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + dest[size] = 0; + + if (!pb_read(stream, dest, (size_t)size)) + return false; + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8((const char*)dest)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return true; +} + +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field) +{ + bool status = true; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED || + PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) + { + if (!pb_message_set_to_defaults(&submsg_iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); + } + } + + /* Submessages can have a separate message-level callback that is called + * before decoding the message. Typically it is used to set callback fields + * inside oneofs. */ + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) + { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; + if (callback->funcs.decode) + { + status = callback->funcs.decode(&substream, field, &callback->arg); + } + } + + /* Now decode the submessage contents */ + if (status) + { + status = pb_decode_inner(&substream, field->submsg_desc, field->pData, 0); + } + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; +} + +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +{ + uint32_t size; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + if (size == 0) + { + /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ + memset(field->pData, 0, (size_t)field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t*)field->pData, (size_t)field->data_size); +} + +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest) +{ + uint_least8_t sign; + int exponent; + uint32_t mantissa; + uint64_t value; + union { float f; uint32_t i; } out; + + if (!pb_decode_fixed64(stream, &value)) + return false; + + /* Decompose input value */ + sign = (uint_least8_t)((value >> 63) & 1); + exponent = (int)((value >> 52) & 0x7FF) - 1023; + mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ + + /* Figure if value is in range representable by floats. */ + if (exponent == 1024) + { + /* Special value */ + exponent = 128; + } + else if (exponent > 127) + { + /* Too large, convert to infinity */ + exponent = 128; + mantissa = 0; + } + else if (exponent < -150) + { + /* Too small, convert to zero */ + exponent = -127; + mantissa = 0; + } + else if (exponent < -126) + { + /* Denormalized */ + mantissa |= 0x1000000; + mantissa >>= (-126 - exponent); + exponent = -127; + } + + /* Round off mantissa */ + mantissa = (mantissa + 1) >> 1; + + /* Check if mantissa went over 2.0 */ + if (mantissa & 0x800000) + { + exponent += 1; + mantissa &= 0x7FFFFF; + mantissa >>= 1; + } + + /* Combine fields */ + out.i = mantissa; + out.i |= (uint32_t)(exponent + 127) << 23; + out.i |= (uint32_t)sign << 31; + + *dest = out.f; + return true; +} +#endif diff --git a/src/ui/nanopb/pb_decode.h b/src/ui/nanopb/pb_decode.h new file mode 100644 index 00000000..b64d95ae --- /dev/null +++ b/src/ui/nanopb/pb_decode.h @@ -0,0 +1,193 @@ +/* pb_decode.h: Functions to decode protocol buffers. Depends on pb_decode.c. + * The main function is pb_decode. You also need an input stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_DECODE_H_INCLUDED +#define PB_DECODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom input streams. You will need to provide + * a callback function to read the bytes from your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause decoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer), + * and rely on pb_read to verify that no-body reads past bytes_left. + * 3) Your callback may be used with substreams, in which case bytes_left + * is different than from the main stream. Don't use bytes_left to compute + * any pointers. + */ +struct pb_istream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; +#else + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); +#endif + + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +#ifndef PB_NO_ERRMSG +#define PB_ISTREAM_EMPTY {0,0,0,0} +#else +#define PB_ISTREAM_EMPTY {0,0,0} +#endif + +/*************************** + * Main decoding functions * + ***************************/ + +/* Decode a single protocol buffers message from input stream into a C structure. + * Returns true on success, false on any failure. + * The actual struct pointed to by dest must match the description in fields. + * Callback fields of the destination structure must be initialized by caller. + * All other fields will be initialized by this function. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_istream_t stream; + * + * // ... read some data into buffer ... + * + * stream = pb_istream_from_buffer(buffer, count); + * pb_decode(&stream, MyMessage_fields, &msg); + */ +bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct); + +/* Extended version of pb_decode, with several options to control + * the decoding process: + * + * PB_DECODE_NOINIT: Do not initialize the fields to default values. + * This is slightly faster if you do not need the default + * values and instead initialize the structure to 0 using + * e.g. memset(). This can also be used for merging two + * messages, i.e. combine already existing data with new + * values. + * + * PB_DECODE_DELIMITED: Input message starts with the message size as varint. + * Corresponds to parseDelimitedFrom() in Google's + * protobuf API. + * + * PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows + * reading null terminated messages. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows + * null-termination. This behaviour is not supported in + * most other protobuf implementations, so PB_DECODE_DELIMITED + * is a better option for compatibility. + * + * Multiple flags can be combined with bitwise or (| operator) + */ +#define PB_DECODE_NOINIT 0x01U +#define PB_DECODE_DELIMITED 0x02U +#define PB_DECODE_NULLTERMINATED 0x04U +bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags); + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT) +#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED) +#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT) +#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED) + +#ifdef PB_ENABLE_MALLOC +/* Release any allocated pointer fields. If you use dynamic allocation, you should + * call this for any successfully decoded message when you are done with it. If + * pb_decode() returns with an error, the message is already released. + */ +void pb_release(const pb_msgdesc_t *fields, void *dest_struct); +#endif + + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an input stream for reading from a memory buffer. + * + * Alternatively, you can use a custom stream that reads directly from e.g. + * a file or a network socket. + */ +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); + +/* Function to read from a pb_istream_t. You can use this if you need to + * read some custom header data, or to read data in field callbacks. + */ +bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Decode the tag for the next field in the stream. Gives the wire type and + * field tag. At end of the message, returns false and sets eof to true. */ +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); + +/* Skip the field payload data, given the wire type. */ +bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); + +/* Decode an integer in the varint format. This works for enum, int32, + * int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); +#else +#define pb_decode_varint pb_decode_varint32 +#endif + +/* Decode an integer in the varint format. This works for enum, int32, + * and uint32 field types. */ +bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); + +/* Decode a bool value in varint format. */ +bool pb_decode_bool(pb_istream_t *stream, bool *dest); + +/* Decode an integer in the zig-zagged svarint format. This works for sint32 + * and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_decode_svarint(pb_istream_t *stream, int64_t *dest); +#else +bool pb_decode_svarint(pb_istream_t *stream, int32_t *dest); +#endif + +/* Decode a fixed32, sfixed32 or float value. You need to pass a pointer to + * a 4-byte wide C variable. */ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest); + +#ifndef PB_WITHOUT_64BIT +/* Decode a fixed64, sfixed64 or double value. You need to pass a pointer to + * a 8-byte wide C variable. */ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest); +#endif + +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Decode a double value into float variable. */ +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest); +#endif + +/* Make a limited-length substream for reading a PB_WT_STRING field. */ +bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); +bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/ui/nanopb/pb_encode.c b/src/ui/nanopb/pb_encode.c new file mode 100644 index 00000000..409fec39 --- /dev/null +++ b/src/ui/nanopb/pb_encode.c @@ -0,0 +1,958 @@ +/* pb_encode.c -- encode a protobuf using minimal resources + * + * 2011 Petteri Aimonen + */ + +#include "pb.h" +#include "pb_encode.h" +#include "pb_common.h" + +/* Use the GCC warn_unused_result attribute to check that all return values + * are propagated correctly. On other compilers and gcc before 3.4.0 just + * ignore the annotation. + */ +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +/************************************** + * Declarations internal to this file * + **************************************/ +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field); +static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field); +static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high); +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); + +#ifdef PB_WITHOUT_64BIT +#define pb_int64_t int32_t +#define pb_uint64_t uint32_t +#else +#define pb_int64_t int64_t +#define pb_uint64_t uint64_t +#endif + +/******************************* + * pb_ostream_t implementation * + *******************************/ + +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + size_t i; + pb_byte_t *dest = (pb_byte_t*)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; +} + +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) +{ + pb_ostream_t stream; +#ifdef PB_BUFFER_ONLY + stream.callback = (void*)1; /* Just a marker value */ +#else + stream.callback = &buf_write; +#endif + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + return stream; +} + +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) +{ + if (count > 0 && stream->callback != NULL) + { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + +#ifdef PB_BUFFER_ONLY + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#endif + } + + stream->bytes_written += count; + return true; +} + +/************************* + * Encode a single field * + *************************/ + +/* Read a bool value without causing undefined behavior even if the value + * is invalid. See issue #434 and + * https://stackoverflow.com/questions/27661768/weird-results-for-conditional + */ +static bool safe_read_bool(const void *pSize) +{ + const char *p = (const char *)pSize; + size_t i; + for (i = 0; i < sizeof(bool); i++) + { + if (p[i] != 0) + return true; + } + return false; +} + +/* Encode a static array. Handles the size calculations and possible packing. */ +static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field) +{ + pb_size_t i; + pb_size_t count; +#ifndef PB_ENCODE_ARRAYS_UNPACKED + size_t size; +#endif + + count = *(pb_size_t*)field->pSize; + + if (count == 0) + return true; + + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + +#ifndef PB_ENCODE_ARRAYS_UNPACKED + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) + { + size = 4 * (size_t)count; + } + else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + size = 8 * (size_t)count; + } + else + { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + void *pData_orig = field->pData; + for (i = 0; i < count; i++) + { + if (!pb_enc_varint(&sizestream, field)) + PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream)); + field->pData = (char*)field->pData + field->data_size; + } + field->pData = pData_orig; + size = sizestream.bytes_written; + } + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + for (i = 0; i < count; i++) + { + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + if (!pb_enc_fixed(stream, field)) + return false; + } + else + { + if (!pb_enc_varint(stream, field)) + return false; + } + + field->pData = (char*)field->pData + field->data_size; + } + } + else /* Unpacked fields */ +#endif + { + for (i = 0; i < count; i++) + { + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) + { + bool status; + void *pData_orig = field->pData; + field->pData = *(void* const*)field->pData; + + if (!field->pData) + { + /* Null pointer in array is treated as empty string / bytes */ + status = pb_encode_tag_for_field(stream, field) && + pb_encode_varint(stream, 0); + } + else + { + status = encode_basic_field(stream, field); + } + + field->pData = pData_orig; + + if (!status) + return false; + } + else + { + if (!encode_basic_field(stream, field)) + return false; + } + field->pData = (char*)field->pData + field->data_size; + } + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is "non-zero". + * This function implements the check for the zero value. */ +static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field) +{ + pb_type_t type = field->type; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) + { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)field->pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)field->pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) + { + /* Proto2 optional fields inside proto3 message, or proto3 + * submessage fields. */ + return safe_read_bool(field->pSize) == false; + } + + /* Rest is proto3 singular fields */ + if (PB_LTYPE(type) == PB_LTYPE_BYTES) + { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData; + return bytes->size == 0; + } + else if (PB_LTYPE(type) == PB_LTYPE_STRING) + { + return *(const char*)field->pData == '\0'; + } + else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) + { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } + else if (PB_LTYPE_IS_SUBMSG(type)) + { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. Note that usually proto3 submessages have + * a separate has_field that is checked earlier in this if. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData)) + { + do + { + if (!pb_check_proto3_default_value(&iter)) + { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; + } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)field->pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } +} + +/* Encode a field with static or pointer allocation, i.e. one whose data + * is available to the encoder directly. */ +static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (!field->pData) + { + /* Missing pointer field */ + return true; + } + + if (!pb_encode_tag_for_field(stream, field)) + return false; + + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + return pb_enc_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return pb_enc_varint(stream, field); + + case PB_LTYPE_FIXED32: + case PB_LTYPE_FIXED64: + return pb_enc_fixed(stream, field); + + case PB_LTYPE_BYTES: + return pb_enc_bytes(stream, field); + + case PB_LTYPE_STRING: + return pb_enc_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + return pb_enc_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + return pb_enc_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +/* Encode a field with callback semantics. This means that a user function is + * called to provide and encode the actual data. */ +static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (field->descriptor->field_callback != NULL) + { + if (!field->descriptor->field_callback(NULL, stream, field)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; +} + +/* Encode a single field of any callback, pointer or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field) +{ + /* Check field presence */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + { + if (*(const pb_size_t*)field->pSize != field->tag) + { + /* Different type oneof field */ + return true; + } + } + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) + { + if (field->pSize) + { + if (safe_read_bool(field->pSize) == false) + { + /* Missing optional field */ + return true; + } + } + else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) + { + /* Proto3 singular field */ + if (pb_check_proto3_default_value(field)) + return true; + } + } + + if (!field->pData) + { + if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED) + PB_RETURN_ERROR(stream, "missing required field"); + + /* Pointer field set to NULL */ + return true; + } + + /* Then encode field contents */ + if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK) + { + return encode_callback_field(stream, field); + } + else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) + { + return encode_array(stream, field); + } + else + { + return encode_basic_field(stream, field); + } +} + +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension) +{ + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension_const(&iter, extension)) + PB_RETURN_ERROR(stream, "invalid extension"); + + return encode_field(stream, &iter); +} + + +/* Walk through all the registered extensions and give them a chance + * to encode themselves. */ +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData; + + while (extension) + { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; +} + +/********************* + * Encode all fields * + *********************/ + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +{ + pb_field_iter_t iter; + if (!pb_field_iter_begin_const(&iter, fields, src_struct)) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) + { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, &iter)) + return false; + } + else + { + /* Regular field */ + if (!encode_field(stream, &iter)) + return false; + } + } while (pb_field_iter_next(&iter)); + + return true; +} + +bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags) +{ + if ((flags & PB_ENCODE_DELIMITED) != 0) + { + return pb_encode_submessage(stream, fields, src_struct); + } + else if ((flags & PB_ENCODE_NULLTERMINATED) != 0) + { + const pb_byte_t zero = 0; + + if (!pb_encode(stream, fields, src_struct)) + return false; + + return pb_write(stream, &zero, 1); + } + else + { + return pb_encode(stream, fields, src_struct); + } +} + +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct) +{ + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; +} + +/******************** + * Helper functions * + ********************/ + +/* This function avoids 64-bit shifts as they are quite slow on many platforms. */ +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high) +{ + size_t i = 0; + pb_byte_t buffer[10]; + pb_byte_t byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + + while (i < 4 && (low != 0 || high != 0)) + { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + } + + if (high) + { + byte = (pb_byte_t)(byte | ((high & 0x07) << 4)); + high >>= 3; + + while (high) + { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(high & 0x7F); + high >>= 7; + } + } + + buffer[i++] = byte; + + return pb_write(stream, buffer, i); +} + +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) +{ + if (value <= 0x7F) + { + /* Fast path: single byte */ + pb_byte_t byte = (pb_byte_t)value; + return pb_write(stream, &byte, 1); + } + else + { +#ifdef PB_WITHOUT_64BIT + return pb_encode_varint_32(stream, value, 0); +#else + return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32)); +#endif + } +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) +{ + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); +} + +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) +{ + uint32_t val = *(const uint32_t*)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); +} + +#ifndef PB_WITHOUT_64BIT +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) +{ + uint64_t val = *(const uint64_t*)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); +} +#endif + +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) +{ + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); +} + +bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field ) +{ + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) + { + case PB_LTYPE_BOOL: + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); +} + +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) +{ + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +{ + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) + { +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; +#ifndef PB_NO_ERRMSG + substream.errmsg = NULL; +#endif + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; +#ifndef PB_NO_ERRMSG + stream->errmsg = substream.errmsg; +#endif + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; +} + +/* Field encoders */ + +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + uint32_t value = safe_read_bool(field->pData) ? 1 : 0; + PB_UNUSED(field); + return pb_encode_varint(stream, value); +} + +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) + { + /* Perform unsigned integer extension */ + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)field->pData; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)field->pData; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)field->pData; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)field->pData; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); + } + else + { + /* Perform signed integer extension */ + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)field->pData; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)field->pData; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)field->pData; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)field->pData; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) + return pb_encode_svarint(stream, value); +#ifdef PB_WITHOUT_64BIT + else if (value < 0) + return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1); +#endif + else + return pb_encode_varint(stream, (pb_uint64_t)value); + + } +} + +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field) +{ +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) + { + return pb_encode_float_as_double(stream, *(float*)field->pData); + } +#endif + + if (field->data_size == sizeof(uint32_t)) + { + return pb_encode_fixed32(stream, field->pData); + } +#ifndef PB_WITHOUT_64BIT + else if (field->data_size == sizeof(uint64_t)) + { + return pb_encode_fixed64(stream, field->pData); + } +#endif + else + { + PB_RETURN_ERROR(stream, "invalid data_size"); + } +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t*)field->pData; + + if (bytes == NULL) + { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) + { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + size_t size = 0; + size_t max_size = (size_t)field->data_size; + const char *str = (const char*)field->pData; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + max_size = (size_t)-1; + } + else + { + /* pb_dec_string() assumes string fields end with a null + * terminator when the type isn't PB_ATYPE_POINTER, so we + * shouldn't allow more than max-1 bytes to be written to + * allow space for the null terminator. + */ + if (max_size == 0) + PB_RETURN_ERROR(stream, "zero-length string"); + + max_size -= 1; + } + + + if (str == NULL) + { + size = 0; /* Treat null pointer as an empty string */ + } + else + { + const char *p = str; + + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') + { + size++; + p++; + } + + if (*p != '\0') + { + PB_RETURN_ERROR(stream, "unterminated string"); + } + } + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8(str)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return pb_encode_string(stream, (const pb_byte_t*)str, size); +} + +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) + { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; + if (callback->funcs.encode) + { + if (!callback->funcs.encode(stream, field, &callback->arg)) + return false; + } + } + + return pb_encode_submessage(stream, field->submsg_desc, field->pData); +} + +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +{ + return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size); +} + +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_encode_float_as_double(pb_ostream_t *stream, float value) +{ + union { float f; uint32_t i; } in; + uint_least8_t sign; + int exponent; + uint64_t mantissa; + + in.f = value; + + /* Decompose input value */ + sign = (uint_least8_t)((in.i >> 31) & 1); + exponent = (int)((in.i >> 23) & 0xFF) - 127; + mantissa = in.i & 0x7FFFFF; + + if (exponent == 128) + { + /* Special value (NaN etc.) */ + exponent = 1024; + } + else if (exponent == -127) + { + if (!mantissa) + { + /* Zero */ + exponent = -1023; + } + else + { + /* Denormalized */ + mantissa <<= 1; + while (!(mantissa & 0x800000)) + { + mantissa <<= 1; + exponent--; + } + mantissa &= 0x7FFFFF; + } + } + + /* Combine fields */ + mantissa <<= 29; + mantissa |= (uint64_t)(exponent + 1023) << 52; + mantissa |= (uint64_t)sign << 63; + + return pb_encode_fixed64(stream, &mantissa); +} +#endif diff --git a/src/ui/nanopb/pb_encode.h b/src/ui/nanopb/pb_encode.h new file mode 100644 index 00000000..88e246a2 --- /dev/null +++ b/src/ui/nanopb/pb_encode.h @@ -0,0 +1,185 @@ +/* pb_encode.h: Functions to encode protocol buffers. Depends on pb_encode.c. + * The main function is pb_encode. You also need an output stream, and the + * field descriptions created by nanopb_generator.py. + */ + +#ifndef PB_ENCODE_H_INCLUDED +#define PB_ENCODE_H_INCLUDED + +#include "pb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure for defining custom output streams. You will need to provide + * a callback function to write the bytes to your storage, which can be + * for example a file or a network socket. + * + * The callback must conform to these rules: + * + * 1) Return false on IO errors. This will cause encoding to abort. + * 2) You can use state to store your own data (e.g. buffer pointer). + * 3) pb_write will update bytes_written after your callback runs. + * 4) Substreams will modify max_size and bytes_written. Don't use them + * to calculate any pointers. + */ +struct pb_ostream_s +{ +#ifdef PB_BUFFER_ONLY + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; +#else + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); +#endif + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + +#ifndef PB_NO_ERRMSG + const char *errmsg; +#endif +}; + +/*************************** + * Main encoding functions * + ***************************/ + +/* Encode a single protocol buffers message from C structure into a stream. + * Returns true on success, false on any failure. + * The actual struct pointed to by src_struct must match the description in fields. + * All required fields in the struct are assumed to have been filled in. + * + * Example usage: + * MyMessage msg = {}; + * uint8_t buffer[64]; + * pb_ostream_t stream; + * + * msg.field1 = 42; + * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + * pb_encode(&stream, MyMessage_fields, &msg); + */ +bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); + +/* Extended version of pb_encode, with several options to control the + * encoding process: + * + * PB_ENCODE_DELIMITED: Prepend the length of message as a varint. + * Corresponds to writeDelimitedTo() in Google's + * protobuf API. + * + * PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other + * protobuf implementations, so PB_ENCODE_DELIMITED + * is a better option for compatibility. + */ +#define PB_ENCODE_DELIMITED 0x02U +#define PB_ENCODE_NULLTERMINATED 0x04U +bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags); + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED) +#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED) + +/* Encode the message to get the size of the encoded data, but do not store + * the data. */ +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct); + +/************************************** + * Functions for manipulating streams * + **************************************/ + +/* Create an output stream for writing into a memory buffer. + * The number of bytes written can be found in stream.bytes_written after + * encoding the message. + * + * Alternatively, you can use a custom stream that writes directly to e.g. + * a file or a network socket. + */ +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); + +/* Pseudo-stream for measuring the size of a message without actually storing + * the encoded data. + * + * Example usage: + * MyMessage msg = {}; + * pb_ostream_t stream = PB_OSTREAM_SIZING; + * pb_encode(&stream, MyMessage_fields, &msg); + * printf("Message size is %d\n", stream.bytes_written); + */ +#ifndef PB_NO_ERRMSG +#define PB_OSTREAM_SIZING {0,0,0,0,0} +#else +#define PB_OSTREAM_SIZING {0,0,0,0} +#endif + +/* Function to write into a pb_ostream_t stream. You can use this if you need + * to append or prepend some custom headers to the message. + */ +bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + + +/************************************************ + * Helper functions for writing field callbacks * + ************************************************/ + +/* Encode field header based on type and field number defined in the field + * structure. Call this from the callback before writing out field contents. */ +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field); + +/* Encode field header by manually specifing wire type. You need to use this + * if you want to write out packed arrays from a callback field. */ +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); + +/* Encode an integer in the varint format. + * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_varint(pb_ostream_t *stream, uint64_t value); +#else +bool pb_encode_varint(pb_ostream_t *stream, uint32_t value); +#endif + +/* Encode an integer in the zig-zagged svarint format. + * This works for sint32 and sint64. */ +#ifndef PB_WITHOUT_64BIT +bool pb_encode_svarint(pb_ostream_t *stream, int64_t value); +#else +bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); +#endif + +/* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); + +/* Encode a fixed32, sfixed32 or float value. + * You need to pass a pointer to a 4-byte wide C variable. */ +bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); + +#ifndef PB_WITHOUT_64BIT +/* Encode a fixed64, sfixed64 or double value. + * You need to pass a pointer to a 8-byte wide C variable. */ +bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); +#endif + +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Encode a float value so that it appears like a double in the encoded + * message. */ +bool pb_encode_float_as_double(pb_ostream_t *stream, float value); +#endif + +/* Encode a submessage field. + * You need to pass the pb_field_t array and pointer to struct, just like + * with pb_encode(). This internally encodes the submessage twice, first to + * calculate message size and then to actually write it out. + */ +bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/ui/nanopb/simple.pb.c b/src/ui/nanopb/simple.pb.c new file mode 100644 index 00000000..a487f136 --- /dev/null +++ b/src/ui/nanopb/simple.pb.c @@ -0,0 +1,12 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.2-dev */ + +#include "simple.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(SimpleMessage, SimpleMessage, AUTO) + + + diff --git a/src/ui/nanopb/simple.pb.h b/src/ui/nanopb/simple.pb.h new file mode 100644 index 00000000..4b8d5671 --- /dev/null +++ b/src/ui/nanopb/simple.pb.h @@ -0,0 +1,47 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.2-dev */ + +#ifndef PB_SIMPLE_PB_H_INCLUDED +#define PB_SIMPLE_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _SimpleMessage { + int32_t lucky_number; +} SimpleMessage; + + +/* Initializer values for message structs */ +#define SimpleMessage_init_default {0} +#define SimpleMessage_init_zero {0} + +/* Field tags (for use in manual encoding/decoding) */ +#define SimpleMessage_lucky_number_tag 1 + +/* Struct field encoding specification for nanopb */ +#define SimpleMessage_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, INT32, lucky_number, 1) +#define SimpleMessage_CALLBACK NULL +#define SimpleMessage_DEFAULT NULL + +extern const pb_msgdesc_t SimpleMessage_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define SimpleMessage_fields &SimpleMessage_msg + +/* Maximum encoded size of messages (where known) */ +#define SimpleMessage_size 11 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/ui/nanopb/simple.proto b/src/ui/nanopb/simple.proto new file mode 100644 index 00000000..5c73a3b2 --- /dev/null +++ b/src/ui/nanopb/simple.proto @@ -0,0 +1,9 @@ +// A very simple protocol definition, consisting of only +// one message. + +syntax = "proto2"; + +message SimpleMessage { + required int32 lucky_number = 1; +} + diff --git a/src/ui/ui.c b/src/ui/ui.c index bb2046b6..a66b35e6 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -24,6 +24,9 @@ #include "../main.h" #include "../crypto/waves.h" #include "transactions/transfer.h" +#include "nanopb/pb_encode.h" +#include "nanopb/pb_decode.h" +#include "nanopb/simple.pb.h" #ifdef TARGET_BLUE #include "blue/ui_menus_blue.h" @@ -174,6 +177,67 @@ void make_allowed_ui_steps(bool is_last) { build_other_data_ui(); } PRINTF("make_allowed_ui_steps end\n"); + //Testing simpe protobuf + /* This is the buffer where we will store our message. */ + PRINTF("init variables\n"); + uint8_t buffer[128]; + size_t message_length; + bool status; + + /* Encode our message */ + //{ + /* Allocate space on the stack to store the message data. + * + * Nanopb generates simple struct definitions for all the messages. + * - check out the contents of simple.pb.h! + * It is a good idea to always initialize your structures + * so that you do not have garbage data from RAM in there. + */ + SimpleMessage message = SimpleMessage_init_zero; + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + /* Fill in the lucky number */ + message.lucky_number = 13; + /* Now we are ready to encode the message! */ + status = pb_encode(&stream, SimpleMessage_fields, &message); + message_length = stream.bytes_written; + + /* Then just check for any errors.. */ + if (!status) + { + PRINTF("Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return ; + } + //} + + /* Now we could transmit the message over network, store it in a file or + * wrap it to a pigeon's leg. + */ + + /* But because we are lazy, we will just decode it immediately. */ + + //{ + //PRINTF("init message\n"); + /* Allocate space for the decoded message. */ + //SimpleMessage message = SimpleMessage_init_zero; + //PRINTF("create stream\n"); + /* Create a stream that reads from the buffer. */ + //pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); + //PRINTF("decode message\n"); + /* Now we are ready to decode the message. */ + //status = pb_decode(&stream, SimpleMessage_fields, &message); + + /* Check for errors... */ + //if (!status) + //{ + // PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + //return ; + //} + + /* Print the data contained in the message. */ + //PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); + //} + //*****END TESTING SIMPLE***** } // Show the transaction details for the user to approve @@ -200,12 +264,4 @@ void show_sign_ui() { ux_flow_init(0, ux_verify_transaction_flow, NULL); #endif // #if TARGET_ID } -} - -void show_processing() { -#if defined(TARGET_BLUE) - UX_DISPLAY(ui_processing_blue, NULL); -#else - ux_flow_init(0, ux_processing_flow, NULL); -#endif } \ No newline at end of file From eb8b899200ca2c442e183fbd19fc6cd62c079fdb Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Mon, 6 Apr 2020 11:13:34 +0400 Subject: [PATCH 02/26] clang format code --- src/ui/ui.c | 119 ++++++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/src/ui/ui.c b/src/ui/ui.c index a66b35e6..a524d2a5 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -177,67 +177,66 @@ void make_allowed_ui_steps(bool is_last) { build_other_data_ui(); } PRINTF("make_allowed_ui_steps end\n"); - //Testing simpe protobuf - /* This is the buffer where we will store our message. */ - PRINTF("init variables\n"); - uint8_t buffer[128]; - size_t message_length; - bool status; - - /* Encode our message */ - //{ - /* Allocate space on the stack to store the message data. - * - * Nanopb generates simple struct definitions for all the messages. - * - check out the contents of simple.pb.h! - * It is a good idea to always initialize your structures - * so that you do not have garbage data from RAM in there. - */ - SimpleMessage message = SimpleMessage_init_zero; - /* Create a stream that will write to our buffer. */ - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - /* Fill in the lucky number */ - message.lucky_number = 13; - /* Now we are ready to encode the message! */ - status = pb_encode(&stream, SimpleMessage_fields, &message); - message_length = stream.bytes_written; - - /* Then just check for any errors.. */ - if (!status) - { - PRINTF("Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return ; - } - //} - - /* Now we could transmit the message over network, store it in a file or - * wrap it to a pigeon's leg. - */ + // Testing simpe protobuf + /* This is the buffer where we will store our message. */ + PRINTF("init variables\n"); + uint8_t buffer[128]; + size_t message_length; + bool status; - /* But because we are lazy, we will just decode it immediately. */ - - //{ - //PRINTF("init message\n"); - /* Allocate space for the decoded message. */ - //SimpleMessage message = SimpleMessage_init_zero; - //PRINTF("create stream\n"); - /* Create a stream that reads from the buffer. */ - //pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); - //PRINTF("decode message\n"); - /* Now we are ready to decode the message. */ - //status = pb_decode(&stream, SimpleMessage_fields, &message); - - /* Check for errors... */ - //if (!status) - //{ - // PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); - //return ; - //} - - /* Print the data contained in the message. */ - //PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); - //} - //*****END TESTING SIMPLE***** + /* Encode our message */ + //{ + /* Allocate space on the stack to store the message data. + * + * Nanopb generates simple struct definitions for all the messages. + * - check out the contents of simple.pb.h! + * It is a good idea to always initialize your structures + * so that you do not have garbage data from RAM in there. + */ + SimpleMessage message = SimpleMessage_init_zero; + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + /* Fill in the lucky number */ + message.lucky_number = 13; + /* Now we are ready to encode the message! */ + status = pb_encode(&stream, SimpleMessage_fields, &message); + message_length = stream.bytes_written; + + /* Then just check for any errors.. */ + if (!status) { + PRINTF("Encoding failed: %s\n", PB_GET_ERROR(&stream)); + return; + } + //} + + /* Now we could transmit the message over network, store it in a file or + * wrap it to a pigeon's leg. + */ + + /* But because we are lazy, we will just decode it immediately. */ + + //{ + // PRINTF("init message\n"); + /* Allocate space for the decoded message. */ + // SimpleMessage message = SimpleMessage_init_zero; + // PRINTF("create stream\n"); + /* Create a stream that reads from the buffer. */ + // pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); + // PRINTF("decode message\n"); + /* Now we are ready to decode the message. */ + // status = pb_decode(&stream, SimpleMessage_fields, &message); + + /* Check for errors... */ + // if (!status) + //{ + // PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + // return ; + //} + + /* Print the data contained in the message. */ + // PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); + //} + //*****END TESTING SIMPLE***** } // Show the transaction details for the user to approve From c3e47fd9fa98fa6c52be4eae36b7e5f382b82b58 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Tue, 7 Apr 2020 10:40:45 +0400 Subject: [PATCH 03/26] add deleted show processing function --- src/ui/ui.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ui/ui.c b/src/ui/ui.c index a524d2a5..46a428af 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -263,4 +263,12 @@ void show_sign_ui() { ux_flow_init(0, ux_verify_transaction_flow, NULL); #endif // #if TARGET_ID } +} + +void show_processing() { +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_processing_blue, NULL); +#else + ux_flow_init(0, ux_processing_flow, NULL); +#endif } \ No newline at end of file From bf81c5833c31bc4820163b246021f8d3bc21cd2f Mon Sep 17 00:00:00 2001 From: Sergey Tolmachev Date: Tue, 7 Apr 2020 15:43:06 +0300 Subject: [PATCH 04/26] rollback nanopb to 0.3.9.3 (from ledger-nanopb) --- src/ui/nanopb/pb.h | 688 +++++++------------- src/ui/nanopb/pb_common.c | 374 +++-------- src/ui/nanopb/pb_common.h | 27 +- src/ui/nanopb/pb_decode.c | 1276 ++++++++++++++++--------------------- src/ui/nanopb/pb_decode.h | 82 +-- src/ui/nanopb/pb_encode.c | 797 ++++++++++------------- src/ui/nanopb/pb_encode.h | 39 +- src/ui/nanopb/simple.pb.c | 13 +- src/ui/nanopb/simple.pb.h | 26 +- src/ui/ui.c | 33 +- 10 files changed, 1293 insertions(+), 2062 deletions(-) diff --git a/src/ui/nanopb/pb.h b/src/ui/nanopb/pb.h index 09c25261..fce1f1b6 100644 --- a/src/ui/nanopb/pb.h +++ b/src/ui/nanopb/pb.h @@ -11,7 +11,7 @@ *****************************************************************/ /* Enable support for dynamically allocated fields */ -/* #define PB_ENABLE_MALLOC 1 */ +/*#define PB_ENABLE_MALLOC 1 */ /* Define this if your CPU / compiler combination does not support * unaligned memory access to packed structures. */ @@ -21,8 +21,11 @@ * A compiler warning will tell if you need this. */ /* #define PB_MAX_REQUIRED_FIELDS 256 */ +/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ +/* #define PB_FIELD_16BIT 1 */ + /* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ -/* #define PB_FIELD_32BIT 1 */ +#define PB_FIELD_32BIT 1 /* Disable support for error messages in order to save some code space. */ /* #define PB_NO_ERRMSG 1 */ @@ -30,22 +33,10 @@ /* Disable support for custom streams (support only memory buffers). */ /* #define PB_BUFFER_ONLY 1 */ -/* Disable support for 64-bit datatypes, for compilers without int64_t - or to save some code space. */ -/* #define PB_WITHOUT_64BIT 1 */ - -/* Don't encode scalar arrays as packed. This is only to be used when - * the decoder on the receiving side cannot process packed scalar arrays. - * Such example is older protobuf.js. */ -/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */ +/* Switch back to the old-style callback function signature. + * This was the default until nanopb-0.2.1. */ +/* #define PB_OLD_CALLBACK_STYLE */ -/* Enable conversion of doubles to floats for platforms that do not - * support 64-bit doubles. Most commonly AVR. */ -/* #define PB_CONVERT_DOUBLE_FLOAT 1 */ - -/* Check whether incoming strings are valid UTF-8 sequences. Slows down - * the string processing slightly and slightly increases code size. */ -/* #define PB_VALIDATE_UTF8 1 */ /****************************************************************** * You usually don't need to change anything below this line. * @@ -55,7 +46,7 @@ /* Version of the nanopb library. Just in case you want to check it in * your own program. */ -#define NANOPB_VERSION nanopb-0.4.2-dev +#define NANOPB_VERSION nanopb-0.4.0-dev /* Include all the system headers needed by nanopb. You will need the * definitions of the following: @@ -75,17 +66,12 @@ #include #include #include -#include #ifdef PB_ENABLE_MALLOC #include #endif #endif -#ifdef __cplusplus -extern "C" { -#endif - /* Macro for defining packed structures (compiler dependent). * This just reduces memory requirements, but is not required. */ @@ -121,19 +107,6 @@ extern "C" { #define PB_UNUSED(x) (void)(x) #endif -/* Harvard-architecture processors may need special attributes for storing - * field information in program memory. */ -#ifndef PB_PROGMEM -#ifdef __AVR__ -#include -#define PB_PROGMEM PROGMEM -#define PB_PROGMEM_READU32(x) pgm_read_dword(&x) -#else -#define PB_PROGMEM -#define PB_PROGMEM_READU32(x) (x) -#endif -#endif - /* Compile-time assertion, used for checking compatible compilation options. * If this does not work properly on your compiler, use * #define PB_NO_STATIC_ASSERT to disable it. @@ -144,20 +117,13 @@ extern "C" { * in the place where the PB_STATIC_ASSERT macro was called. */ #ifndef PB_NO_STATIC_ASSERT -# ifndef PB_STATIC_ASSERT -# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - /* C11 standard _Static_assert mechanism */ -# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG); -# else - /* Classic negative-size-array static assert mechanism */ -# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; -# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) -# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER -# endif -# endif +#ifndef PB_STATIC_ASSERT +#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#endif #else - /* Static asserts disabled by PB_NO_STATIC_ASSERT */ -# define PB_STATIC_ASSERT(COND,MSG) +#define PB_STATIC_ASSERT(COND,MSG) #endif /* Number of required fields to keep track of. */ @@ -169,13 +135,6 @@ extern "C" { #error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). #endif -#ifdef PB_WITHOUT_64BIT -#ifdef PB_CONVERT_DOUBLE_FLOAT -/* Cannot use doubles without 64-bit types */ -#undef PB_CONVERT_DOUBLE_FLOAT -#endif -#endif - /* List of possible field types. These are used in the autogenerated code. * Least-significant 4 bits tell the scalar type * Most-significant 4 bits specify repeated/required/packed etc. @@ -186,69 +145,59 @@ typedef uint_least8_t pb_type_t; /**** Field data types ****/ /* Numeric types */ -#define PB_LTYPE_BOOL 0x00U /* bool */ -#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */ -#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */ -#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */ -#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */ -#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */ +#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ /* Marker for last packable field type. */ -#define PB_LTYPE_LAST_PACKABLE 0x05U +#define PB_LTYPE_LAST_PACKABLE 0x04 /* Byte array with pre-allocated buffer. * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ -#define PB_LTYPE_BYTES 0x06U +#define PB_LTYPE_BYTES 0x05 /* String with pre-allocated buffer. * data_size is the maximum length. */ -#define PB_LTYPE_STRING 0x07U +#define PB_LTYPE_STRING 0x06 /* Submessage * submsg_fields is pointer to field descriptions */ -#define PB_LTYPE_SUBMESSAGE 0x08U - -/* Submessage with pre-decoding callback - * The pre-decoding callback is stored as pb_callback_t right before pSize. - * submsg_fields is pointer to field descriptions */ -#define PB_LTYPE_SUBMSG_W_CB 0x09U +#define PB_LTYPE_SUBMESSAGE 0x07 /* Extension pseudo-field * The field contains a pointer to pb_extension_t */ -#define PB_LTYPE_EXTENSION 0x0AU +#define PB_LTYPE_EXTENSION 0x08 /* Byte array with inline, pre-allocated byffer. * data_size is the length of the inline, allocated buffer. * This differs from PB_LTYPE_BYTES by defining the element as * pb_byte_t[data_size] rather than pb_bytes_array_t. */ -#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 /* Number of declared LTYPES */ -#define PB_LTYPES_COUNT 0x0CU -#define PB_LTYPE_MASK 0x0FU +#define PB_LTYPES_COUNT 0x0A +#define PB_LTYPE_MASK 0x0F /**** Field repetition rules ****/ -#define PB_HTYPE_REQUIRED 0x00U -#define PB_HTYPE_OPTIONAL 0x10U -#define PB_HTYPE_SINGULAR 0x10U -#define PB_HTYPE_REPEATED 0x20U -#define PB_HTYPE_FIXARRAY 0x20U -#define PB_HTYPE_ONEOF 0x30U -#define PB_HTYPE_MASK 0x30U +#define PB_HTYPE_REQUIRED 0x00 +#define PB_HTYPE_OPTIONAL 0x10 +#define PB_HTYPE_REPEATED 0x20 +#define PB_HTYPE_ONEOF 0x30 +#define PB_HTYPE_MASK 0x30 /**** Field allocation types ****/ -#define PB_ATYPE_STATIC 0x00U -#define PB_ATYPE_POINTER 0x80U -#define PB_ATYPE_CALLBACK 0x40U -#define PB_ATYPE_MASK 0xC0U +#define PB_ATYPE_STATIC 0x00 +#define PB_ATYPE_POINTER 0x80 +#define PB_ATYPE_CALLBACK 0x40 +#define PB_ATYPE_MASK 0xC0 #define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) #define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) #define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) -#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \ - PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB) /* Data type used for storing sizes of struct fields * and array counts. @@ -256,9 +205,12 @@ typedef uint_least8_t pb_type_t; #if defined(PB_FIELD_32BIT) typedef uint32_t pb_size_t; typedef int32_t pb_ssize_t; -#else +#elif defined(PB_FIELD_16BIT) typedef uint_least16_t pb_size_t; typedef int_least16_t pb_ssize_t; +#else + typedef uint_least8_t pb_size_t; + typedef int_least8_t pb_ssize_t; #endif #define PB_SIZE_MAX ((pb_size_t)-1) @@ -268,51 +220,31 @@ typedef uint_least8_t pb_type_t; */ typedef uint_least8_t pb_byte_t; -/* Forward declaration of struct types */ -typedef struct pb_istream_s pb_istream_t; -typedef struct pb_ostream_s pb_ostream_t; -typedef struct pb_field_iter_s pb_field_iter_t; - /* This structure is used in auto-generated constants * to specify struct fields. + * You can change field sizes if you need structures + * larger than 256 bytes or field tags larger than 256. + * The compiler should complain if your .proto has such + * structures. Fix that by defining PB_FIELD_16BIT or + * PB_FIELD_32BIT. */ PB_PACKED_STRUCT_START -typedef struct pb_msgdesc_s pb_msgdesc_t; -struct pb_msgdesc_s { - pb_size_t field_count; - const uint32_t *field_info; - const pb_msgdesc_t * const * submsg_info; - const pb_byte_t *default_value; - - bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field); +typedef struct pb_field_s pb_field_t; +struct pb_field_s { + pb_size_t tag; + pb_type_t type; + pb_size_t data_offset; /* Offset of field data, relative to previous field. */ + pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ + pb_size_t data_size; /* Data size in bytes for a single item */ + pb_size_t array_size; /* Maximum number of entries in array */ + + /* Field definitions for submessage + * OR default value for all other non-array, non-callback types + * If null, then field will zeroed. */ + const void *ptr; } pb_packed; PB_PACKED_STRUCT_END -/* Iterator for message descriptor */ -struct pb_field_iter_s { - const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */ - void *message; /* Pointer to start of the structure */ - - pb_size_t index; /* Index of the field */ - pb_size_t field_info_index; /* Index to descriptor->field_info array */ - pb_size_t required_field_index; /* Index that counts only the required fields */ - pb_size_t submessage_index; /* Index that counts only submessages */ - - pb_size_t tag; /* Tag of current field */ - pb_size_t data_size; /* sizeof() of a single item */ - pb_size_t array_size; /* Number of array entries */ - pb_type_t type; /* Type of current field */ - - void *pField; /* Pointer to current field in struct */ - void *pData; /* Pointer to current data contents. Different than pField for arrays and pointers. */ - void *pSize; /* Pointer to count/has field */ - - const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */ -}; - -/* For compatibility with legacy code */ -typedef pb_field_iter_t pb_field_t; - /* Make sure that the standard integer types are of the expected sizes. * Otherwise fixed32/fixed64 fields can break. * @@ -355,22 +287,28 @@ typedef struct pb_bytes_array_s pb_bytes_array_t; * * The callback can be null if you want to skip a field. */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; typedef struct pb_callback_s pb_callback_t; struct pb_callback_s { - /* Callback functions receive a pointer to the arg field. - * You can access the value of the field as *arg, and modify it if needed. - */ +#ifdef PB_OLD_CALLBACK_STYLE + /* Deprecated since nanopb-0.2.1 */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); + } funcs; +#else + /* New function signature, which allows modifying arg contents in callback. */ union { bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); } funcs; +#endif /* Free arg for use by callback */ void *arg; }; -extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field); - /* Wire types. Library user needs these only in encoder callbacks. */ typedef enum { PB_WT_VARINT = 0, @@ -428,8 +366,6 @@ struct pb_extension_s { bool found; }; -#define pb_extension_init_zero {NULL,NULL,NULL,false} - /* Memory allocation functions to use. You can define pb_realloc and * pb_free to custom functions if you want. */ #ifdef PB_ENABLE_MALLOC @@ -442,7 +378,7 @@ struct pb_extension_s { #endif /* This is used to inform about need to regenerate .pb.h/.pb.c files. */ -#define PB_PROTO_HEADER_VERSION 40 +#define PB_PROTO_HEADER_VERSION 30 /* These macros are used to declare pb_field_t's in the constant array. */ /* Size of a structure member, in bytes. */ @@ -451,315 +387,106 @@ struct pb_extension_s { #define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) /* Delta from start of one member to the start of another member. */ #define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) - -/* Force expansion of macro value */ -#define PB_EXPAND(x) x - -/* Binding of a message field set into a specific structure */ -#define PB_BIND(msgname, structname, width) \ - const uint32_t structname ## _field_info[] PB_PROGMEM = \ - { \ - msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \ - 0 \ - }; \ - const pb_msgdesc_t* const structname ## _submsg_info[] = \ - { \ - msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \ - NULL \ - }; \ - const pb_msgdesc_t structname ## _msg = \ - { \ - 0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \ - structname ## _field_info, \ - structname ## _submsg_info, \ - msgname ## _DEFAULT, \ - msgname ## _CALLBACK, \ - }; \ - msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname) - -#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1 - -#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO(1, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO(2, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO(4, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO(8, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) \ - PB_FIELDINFO_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ - PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \ - PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \ - PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \ - PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname)) - -#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT(1, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT(2, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT(4, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT(8, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \ - PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag) - -#define PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag) \ - PB_FIELDINFO_ASSERT_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \ - PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \ - PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \ - PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \ - PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname)) - -#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) -#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) -#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname) -#define PB_DATA_OFFSET_REQUIRED(structname, fieldname) offsetof(structname, fieldname) -#define PB_DATA_OFFSET_SINGULAR(structname, fieldname) offsetof(structname, fieldname) -#define PB_DATA_OFFSET_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname)) -#define PB_DATA_OFFSET_OPTIONAL(structname, fieldname) offsetof(structname, fieldname) -#define PB_DATA_OFFSET_REPEATED(structname, fieldname) offsetof(structname, fieldname) -#define PB_DATA_OFFSET_FIXARRAY(structname, fieldname) offsetof(structname, fieldname) - -#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SIZE_OFFSET_ ## htype(structname, fieldname) -#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SIZE_OFFSET_PTR_ ## htype(structname, fieldname) -#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SIZE_OFFSET_CB_ ## htype(structname, fieldname) -#define PB_SIZE_OFFSET_REQUIRED(structname, fieldname) 0 -#define PB_SIZE_OFFSET_SINGULAR(structname, fieldname) 0 -#define PB_SIZE_OFFSET_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname)) -#define PB_SIZE_OFFSET_ONEOF2(structname, fullname, unionname) PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) -#define PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname) -#define PB_SIZE_OFFSET_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname) -#define PB_SIZE_OFFSET_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count) -#define PB_SIZE_OFFSET_FIXARRAY(structname, fieldname) 0 -#define PB_SIZE_OFFSET_PTR_REQUIRED(structname, fieldname) 0 -#define PB_SIZE_OFFSET_PTR_SINGULAR(structname, fieldname) 0 -#define PB_SIZE_OFFSET_PTR_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname) -#define PB_SIZE_OFFSET_PTR_OPTIONAL(structname, fieldname) 0 -#define PB_SIZE_OFFSET_PTR_REPEATED(structname, fieldname) PB_SIZE_OFFSET_REPEATED(structname, fieldname) -#define PB_SIZE_OFFSET_PTR_FIXARRAY(structname, fieldname) 0 -#define PB_SIZE_OFFSET_CB_REQUIRED(structname, fieldname) 0 -#define PB_SIZE_OFFSET_CB_SINGULAR(structname, fieldname) 0 -#define PB_SIZE_OFFSET_CB_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname) -#define PB_SIZE_OFFSET_CB_OPTIONAL(structname, fieldname) 0 -#define PB_SIZE_OFFSET_CB_REPEATED(structname, fieldname) 0 -#define PB_SIZE_OFFSET_CB_FIXARRAY(structname, fieldname) 0 - -#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_ARRAY_SIZE_ ## htype(structname, fieldname) -#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_ARRAY_SIZE_PTR_ ## htype(structname, fieldname) -#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1 -#define PB_ARRAY_SIZE_REQUIRED(structname, fieldname) 1 -#define PB_ARRAY_SIZE_SINGULAR(structname, fieldname) 1 -#define PB_ARRAY_SIZE_OPTIONAL(structname, fieldname) 1 -#define PB_ARRAY_SIZE_ONEOF(structname, fieldname) 1 -#define PB_ARRAY_SIZE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname) -#define PB_ARRAY_SIZE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname) -#define PB_ARRAY_SIZE_PTR_REQUIRED(structname, fieldname) 1 -#define PB_ARRAY_SIZE_PTR_SINGULAR(structname, fieldname) 1 -#define PB_ARRAY_SIZE_PTR_OPTIONAL(structname, fieldname) 1 -#define PB_ARRAY_SIZE_PTR_ONEOF(structname, fieldname) 1 -#define PB_ARRAY_SIZE_PTR_REPEATED(structname, fieldname) 1 -#define PB_ARRAY_SIZE_PTR_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0]) - -#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DATA_SIZE_ ## htype(structname, fieldname) -#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DATA_SIZE_PTR_ ## htype(structname, fieldname) -#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DATA_SIZE_CB_ ## htype(structname, fieldname) -#define PB_DATA_SIZE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) -#define PB_DATA_SIZE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_PTR_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_PTR_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_PTR_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_PTR_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0]) -#define PB_DATA_SIZE_PTR_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0]) -#define PB_DATA_SIZE_PTR_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0]) -#define PB_DATA_SIZE_CB_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_CB_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_CB_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_CB_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) -#define PB_DATA_SIZE_CB_REPEATED(structname, fieldname) pb_membersize(structname, fieldname) -#define PB_DATA_SIZE_CB_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname) - -#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple) -#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname -#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername -#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname - -#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \ - PB_SUBMSG_INFO_ ## htype(ltype, structname, fieldname) - -#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) -#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) -#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) -#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname)) -#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) -#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE) -#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) -#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE) -#define PB_SUBMSG_INFO_BOOL(t) -#define PB_SUBMSG_INFO_BYTES(t) -#define PB_SUBMSG_INFO_DOUBLE(t) -#define PB_SUBMSG_INFO_ENUM(t) -#define PB_SUBMSG_INFO_UENUM(t) -#define PB_SUBMSG_INFO_FIXED32(t) -#define PB_SUBMSG_INFO_FIXED64(t) -#define PB_SUBMSG_INFO_FLOAT(t) -#define PB_SUBMSG_INFO_INT32(t) -#define PB_SUBMSG_INFO_INT64(t) -#define PB_SUBMSG_INFO_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t) -#define PB_SUBMSG_INFO_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t) -#define PB_SUBMSG_INFO_SFIXED32(t) -#define PB_SUBMSG_INFO_SFIXED64(t) -#define PB_SUBMSG_INFO_SINT32(t) -#define PB_SUBMSG_INFO_SINT64(t) -#define PB_SUBMSG_INFO_STRING(t) -#define PB_SUBMSG_INFO_UINT32(t) -#define PB_SUBMSG_INFO_UINT64(t) -#define PB_SUBMSG_INFO_EXTENSION(t) -#define PB_SUBMSG_INFO_FIXED_LENGTH_BYTES(t) -#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg), - -/* The field descriptors use a variable width format, with width of either - * 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always - * encode the descriptor size, 6 lowest bits of field tag number, and 8 bits - * of the field type. - * - * Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words. - * - * Formats, listed starting with the least significant bit of the first word. - * 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size] - * - * 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset] - * [16-bit data_offset] [12-bit data_size] [4-bit tag>>6] - * - * 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size] - * [8-bit size_offset] [24-bit tag>>6] - * [32-bit data_offset] - * [32-bit data_size] - * - * 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved] - * [8-bit size_offset] [24-bit tag>>6] - * [32-bit data_offset] - * [32-bit data_size] - * [32-bit array_size] - * [32-bit reserved] - * [32-bit reserved] - * [32-bit reserved] - */ - -#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \ - (0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \ - (((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)), - -#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \ - (1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \ - (((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)), - -#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \ - (2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \ - ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ - (data_offset), (data_size), - -#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \ - (3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \ - ((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ - (data_offset), (data_size), (array_size), 0, 0, 0, - -/* These assertions verify that the field information fits in the allocated space. - * The generator tries to automatically determine the correct width that can fit all - * data associated with a message. These asserts will fail only if there has been a - * problem in the automatic logic - this may be worth reporting as a bug. As a workaround, - * you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting - * descriptorsize option in .options file. +/* Marks the end of the field list */ +#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} + +/* Macros for filling in the data_offset field */ +/* data_offset for first field in a message */ +#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) +/* data_offset for subsequent fields */ +#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) +/* data offset for subsequent fields inside an union (oneof) */ +#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) +/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ +#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ + ? PB_DATAOFFSET_FIRST(st, m1, m2) \ + : PB_DATAOFFSET_OTHER(st, m1, m2)) + +/* Required fields are the simplest. They just have delta (padding) from + * previous field end, and the size of the field. Pointer is used for + * submessages and default values. */ -#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<2GB messages with nanopb anyway. +#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional fields add the delta to the has_ variable. */ +#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, \ + pb_delta(st, has_ ## m, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Repeated fields have a _count field and also the maximum number of entries. */ +#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ + fd, \ + pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), \ + pb_arraysize(st, m), ptr} + +/* Allocated fields carry the size of the actual data, not the pointer */ +#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Optional fields don't need a has_ variable, as information would be redundant */ +#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Same as optional fields*/ +#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m[0]), 0, ptr} + +/* Repeated fields have a _count field and a pointer to array of pointers */ +#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ + fd, pb_delta(st, m ## _count, m), \ + pb_membersize(st, m[0]), 0, ptr} + +/* Callbacks are much like required fields except with special datatype. */ +#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ + fd, 0, pb_membersize(st, m), 0, ptr} + +/* Optional extensions don't have the has_ field, as that would be redundant. + * Furthermore, the combination of OPTIONAL without has_ field is used + * for indicating proto3 style fields. Extensions exist in proto2 mode only, + * so they should be encoded according to proto2 rules. To avoid the conflict, + * extensions are marked as REQUIRED instead. */ -#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \ - PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag) - -#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \ - PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag) -#endif +#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ + 0, \ + 0, \ + pb_membersize(st, m), 0, ptr} +#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) -/* Automatic picking of FIELDINFO width: - * Uses width 1 when possible, otherwise resorts to width 2. - * This is used when PB_BIND() is called with "AUTO" as the argument. - * The generator will give explicit size argument when it knows that a message - * structure grows beyond 1-word format limits. - */ -#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FIELDINFO_WIDTH_ ## atype(htype, ltype) -#define PB_FIELDINFO_WIDTH_STATIC(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype) -#define PB_FIELDINFO_WIDTH_POINTER(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype) -#define PB_FIELDINFO_WIDTH_CALLBACK(htype, ltype) 2 -#define PB_FIELDINFO_WIDTH_REQUIRED(ltype) PB_FIELDINFO_WIDTH_ ## ltype -#define PB_FIELDINFO_WIDTH_SINGULAR(ltype) PB_FIELDINFO_WIDTH_ ## ltype -#define PB_FIELDINFO_WIDTH_OPTIONAL(ltype) PB_FIELDINFO_WIDTH_ ## ltype -#define PB_FIELDINFO_WIDTH_ONEOF(ltype) PB_FIELDINFO_WIDTH_ ## ltype -#define PB_FIELDINFO_WIDTH_REPEATED(ltype) 2 -#define PB_FIELDINFO_WIDTH_FIXARRAY(ltype) 2 -#define PB_FIELDINFO_WIDTH_BOOL 1 -#define PB_FIELDINFO_WIDTH_BYTES 2 -#define PB_FIELDINFO_WIDTH_DOUBLE 1 -#define PB_FIELDINFO_WIDTH_ENUM 1 -#define PB_FIELDINFO_WIDTH_UENUM 1 -#define PB_FIELDINFO_WIDTH_FIXED32 1 -#define PB_FIELDINFO_WIDTH_FIXED64 1 -#define PB_FIELDINFO_WIDTH_FLOAT 1 -#define PB_FIELDINFO_WIDTH_INT32 1 -#define PB_FIELDINFO_WIDTH_INT64 1 -#define PB_FIELDINFO_WIDTH_MESSAGE 2 -#define PB_FIELDINFO_WIDTH_MSG_W_CB 2 -#define PB_FIELDINFO_WIDTH_SFIXED32 1 -#define PB_FIELDINFO_WIDTH_SFIXED64 1 -#define PB_FIELDINFO_WIDTH_SINT32 1 -#define PB_FIELDINFO_WIDTH_SINT64 1 -#define PB_FIELDINFO_WIDTH_STRING 2 -#define PB_FIELDINFO_WIDTH_UINT32 1 -#define PB_FIELDINFO_WIDTH_UINT64 1 -#define PB_FIELDINFO_WIDTH_EXTENSION 1 -#define PB_FIELDINFO_WIDTH_FIXED_LENGTH_BYTES 2 +#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ + PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) /* The mapping from protobuf types to LTYPEs is done using these macros. */ -#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL +#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT #define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES #define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 #define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT @@ -770,7 +497,6 @@ struct pb_extension_s { #define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT #define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT #define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE -#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB #define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 #define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 #define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT @@ -781,6 +507,59 @@ struct pb_extension_s { #define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION #define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES +/* This is the actual macro used in field descriptions. + * It takes these arguments: + * - Field tag number + * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, + * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 + * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION + * - Field rules: REQUIRED, OPTIONAL or REPEATED + * - Allocation: STATIC, CALLBACK or POINTER + * - Placement: FIRST or OTHER, depending on if this is the first field in structure. + * - Message name + * - Field name + * - Previous field name (or field name again for first field) + * - Pointer to default value or submsg fields. + */ + +#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ ## rules ## _ ## allocation(tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +/* Field description for oneof fields. This requires taking into account the + * union name also, that's why a separate set of macros is needed. + */ +#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m), 0, ptr} + +#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, u.m), \ + pb_membersize(st, u.m[0]), 0, ptr} + +#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + +#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ + {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ + fd, pb_delta(st, which_ ## u, m), \ + pb_membersize(st, m[0]), 0, ptr} + +#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ + PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ + PB_DATAOFFSET_ ## placement(message, field, prevfield), \ + PB_LTYPE_MAP_ ## type, ptr) + /* These macros are used for giving out error messages. * They are mostly a debugging aid; the main error information * is the true/false return value from functions. @@ -792,7 +571,14 @@ struct pb_extension_s { * PB_GET_ERROR() always returns a pointer to a string. * PB_RETURN_ERROR() sets the error and returns false from current * function. + * G_depth is a global that should be initialized to 0 when + * creating an input stream. It helps tracking the level of the + * call stack when instrumentation is enabled + * (set `INTRUMENT_FUNCTION += -finstrument-functions` in your + * Makfile to do so) */ +extern int G_depth; + #ifdef PB_NO_ERRMSG #define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) #define PB_GET_ERROR(stream) "(errmsg disabled)" @@ -803,28 +589,4 @@ struct pb_extension_s { #define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false -#ifdef __cplusplus -} /* extern "C" */ #endif - -#ifdef __cplusplus -#if __cplusplus >= 201103L -#define PB_CONSTEXPR constexpr -#else // __cplusplus >= 201103L -#define PB_CONSTEXPR -#endif // __cplusplus >= 201103L - -#if __cplusplus >= 201703L -#define PB_INLINE_CONSTEXPR inline constexpr -#else // __cplusplus >= 201703L -#define PB_INLINE_CONSTEXPR PB_CONSTEXPR -#endif // __cplusplus >= 201703L - -namespace nanopb { -// Each type will be partially specialized by the generator. -template struct MessageDescriptor; -} // namespace nanopb -#endif /* __cplusplus */ - -#endif - diff --git a/src/ui/nanopb/pb_common.c b/src/ui/nanopb/pb_common.c index 64eebe39..adfa747a 100644 --- a/src/ui/nanopb/pb_common.c +++ b/src/ui/nanopb/pb_common.c @@ -4,329 +4,107 @@ */ #include "pb_common.h" +#include "os.h" -static bool load_descriptor_values(pb_field_iter_t *iter) -{ - uint32_t word0; - uint32_t data_offset; - uint_least8_t format; - int_least8_t size_offset; - if (iter->index >= iter->descriptor->field_count) - return false; - word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); - format = word0 & 3; - iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); - iter->type = (pb_type_t)((word0 >> 8) & 0xFF); - - if (format == 0) - { - /* 1-word format */ - iter->array_size = 1; - size_offset = (int_least8_t)((word0 >> 24) & 0x0F); - data_offset = (word0 >> 16) & 0xFF; - iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); - } - else if (format == 1) - { - /* 2-word format */ - uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); - - iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); - iter->tag = (pb_size_t)(iter->tag | ((word1 >> 28) << 6)); - size_offset = (int_least8_t)((word0 >> 28) & 0x0F); - data_offset = word1 & 0xFFFF; - iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); - } - else if (format == 2) - { - /* 4-word format */ - uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); - uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); - uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); - - iter->array_size = (pb_size_t)(word0 >> 16); - iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); - size_offset = (int_least8_t)(word1 & 0xFF); - data_offset = word2; - iter->data_size = (pb_size_t)word3; - } - else - { - /* 8-word format */ - uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]); - uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]); - uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]); - uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]); - - iter->array_size = (pb_size_t)word4; - iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); - size_offset = (int_least8_t)(word1 & 0xFF); - data_offset = word2; - iter->data_size = (pb_size_t)word3; - } - iter->pField = (char*)iter->message + data_offset; - - if (size_offset) - { - iter->pSize = (char*)iter->pField - size_offset; - } - else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && - (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || - PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) - { - /* Fixed count array */ - iter->pSize = &iter->array_size; - } - else - { - iter->pSize = NULL; - } - - if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) - { - iter->pData = *(void**)iter->pField; - } - else - { - iter->pData = iter->pField; - } - - if (PB_LTYPE_IS_SUBMSG(iter->type)) - { - iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index]; - } - else - { - iter->submsg_desc = NULL; - } - - return true; +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) +{ + iter->start = (const pb_field_t *)PIC(fields); + iter->pos = (const pb_field_t *)PIC(fields); + iter->required_field_index = 0; + iter->dest_struct = dest_struct; + iter->pData = (char*)dest_struct + iter->pos->data_offset; + iter->pSize = (char*)iter->pData + iter->pos->size_offset; + return (iter->pos->tag != 0); } -static void advance_iterator(pb_field_iter_t *iter) +bool pb_field_iter_next(pb_field_iter_t *iter) { - iter->index++; + const pb_field_t *prev_field = ((const pb_field_t *)PIC(iter->pos)); - if (iter->index >= iter->descriptor->field_count) + if (prev_field->tag == 0) { - /* Restart */ - iter->index = 0; - iter->field_info_index = 0; - iter->submessage_index = 0; - iter->required_field_index = 0; + /* Handle empty message types, where the first field is already the terminator. + * In other cases, the iter->pos never points to the terminator. */ + return false; + } + + iter->pos = ((const pb_field_t *)PIC(iter->pos))+1; + + if (((const pb_field_t *)PIC(iter->pos))->tag == 0) + { + /* Wrapped back to beginning, reinitialize */ + (void)pb_field_iter_begin(iter, ((const pb_field_t *)PIC(iter->start)), iter->dest_struct); + return false; } else { - /* Increment indexes based on previous field type. - * All field info formats have the following fields: - * - lowest 2 bits tell the amount of words in the descriptor (2^n words) - * - bits 2..7 give the lowest bits of tag number. - * - bits 8..15 give the field type. - */ - uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); - pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; - pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); - - iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len); - - if (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED) + /* Increment the pointers based on previous field size */ + size_t prev_size = prev_field->data_size; + + if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && + PB_HTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_HTYPE_ONEOF && + ((const pb_field_t *)PIC(iter->pos))->data_offset == PB_SIZE_MAX) { - iter->required_field_index++; + /* Don't advance pointers inside unions */ + return true; } - - if (PB_LTYPE_IS_SUBMSG(prev_type)) + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && + PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) { - iter->submessage_index++; + /* In static arrays, the data_size tells the size of a single entry and + * array_size is the number of entries */ + prev_size *= prev_field->array_size; } - } -} - -bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message) -{ - memset(iter, 0, sizeof(*iter)); - iter->descriptor = desc; - iter->message = message; - return load_descriptor_values(iter); -} - -bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension) -{ - const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg; - bool status; - - uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); - if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) - { - /* For pointer extensions, the pointer is stored directly - * in the extension structure. This avoids having an extra - * indirection. */ - status = pb_field_iter_begin(iter, msg, &extension->dest); - } - else - { - status = pb_field_iter_begin(iter, msg, extension->dest); - } - - iter->pSize = &extension->found; - return status; -} - -bool pb_field_iter_next(pb_field_iter_t *iter) -{ - advance_iterator(iter); - (void)load_descriptor_values(iter); - return iter->index != 0; -} - -bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) -{ - if (iter->tag == tag) - { - return true; /* Nothing to do, correct field already. */ - } - else - { - pb_size_t start = iter->index; - uint32_t fieldinfo; - - do + else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) { - /* Advance iterator but don't load values yet */ - advance_iterator(iter); - - /* Do fast check for tag number match */ - fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]); - - if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) - { - /* Good candidate, check further */ - (void)load_descriptor_values(iter); - - if (iter->tag == tag && - PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) - { - /* Found it */ - return true; - } - } - } while (iter->index != start); + /* Pointer fields always have a constant size in the main structure. + * The data_size only applies to the dynamically allocated area. */ + prev_size = sizeof(void*); + } - /* Searched all the way back to start, and found nothing. */ - (void)load_descriptor_values(iter); - return false; + if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) + { + /* Count the required fields, in order to check their presence in the + * decoder. */ + iter->required_field_index++; + } + + iter->pData = (char*)iter->pData + prev_size + ((const pb_field_t *)PIC(iter->pos))->data_offset; + iter->pSize = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->size_offset; + return true; } } -static void *pb_const_cast(const void *p) -{ - /* Note: this casts away const, in order to use the common field iterator - * logic for both encoding and decoding. The cast is done using union - * to avoid spurious compiler warnings. */ - union { - void *p1; - const void *p2; - } t; - t.p2 = p; - return t.p1; -} - -bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message) -{ - return pb_field_iter_begin(iter, desc, pb_const_cast(message)); -} - -bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension) -{ - return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension)); -} - -bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) { - if (field->data_size == sizeof(pb_callback_t)) - { - pb_callback_t *pCallback = (pb_callback_t*)field->pData; - - if (pCallback != NULL) + const pb_field_t *start = ((const pb_field_t *)PIC(iter->pos)); + + do { + if (((const pb_field_t *)PIC(iter->pos))->tag == tag && + PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) != PB_LTYPE_EXTENSION) { - if (istream != NULL && pCallback->funcs.decode != NULL) - { - return pCallback->funcs.decode(istream, field, &pCallback->arg); - } - - if (ostream != NULL && pCallback->funcs.encode != NULL) - { - return pCallback->funcs.encode(ostream, field, &pCallback->arg); - } + /* Found the wanted field */ + return true; } - } - - return true; /* Success, but didn't do anything */ - + + (void)pb_field_iter_next(iter); + } while (((const pb_field_t *)PIC(iter->pos)) != start); + + /* Searched all the way back to start, and found nothing. */ + return false; } -#ifdef PB_VALIDATE_UTF8 +extern void _ebss; -/* This function checks whether a string is valid UTF-8 text. - * - * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c - * Original copyright: Markus Kuhn 2005-03-30 - * Licensed under "Short code license", which allows use under MIT license or - * any compatible with it. - */ +//Return true if there is less than MIN_BSS_STACK_GAP bytes available in the stack +bool check_stack_overflow(uint16_t min_bss_stack_gap){ + uint32_t stack_top = 0; -bool pb_validate_utf8(const char *str) -{ - const pb_byte_t *s = (const pb_byte_t*)str; - while (*s) - { - if (*s < 0x80) - { - /* 0xxxxxxx */ - s++; - } - else if ((s[0] & 0xe0) == 0xc0) - { - /* 110XXXXx 10xxxxxx */ - if ((s[1] & 0xc0) != 0x80 || - (s[0] & 0xfe) == 0xc0) /* overlong? */ - return false; - else - s += 2; - } - else if ((s[0] & 0xf0) == 0xe0) - { - /* 1110XXXX 10Xxxxxx 10xxxxxx */ - if ((s[1] & 0xc0) != 0x80 || - (s[2] & 0xc0) != 0x80 || - (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ - (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ - (s[0] == 0xef && s[1] == 0xbf && - (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ - return false; - else - s += 3; - } - else if ((s[0] & 0xf8) == 0xf0) - { - /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ - if ((s[1] & 0xc0) != 0x80 || - (s[2] & 0xc0) != 0x80 || - (s[3] & 0xc0) != 0x80 || - (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ - (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ - return false; - else - s += 4; - } - else - { - return false; - } + //PRINTF("+++++++Stack remaining: CUR STACK ADDR: %p, EBSS: %p, diff: %d\n", &stack_top, &_ebss, ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); + if(((uintptr_t)&stack_top) < (((uintptr_t)&_ebss) + min_bss_stack_gap)){ + return true; } - - return true; + + return false; } - -#endif - diff --git a/src/ui/nanopb/pb_common.h b/src/ui/nanopb/pb_common.h index 47fa2c99..60b3d374 100644 --- a/src/ui/nanopb/pb_common.h +++ b/src/ui/nanopb/pb_common.h @@ -11,18 +11,20 @@ extern "C" { #endif +/* Iterator for pb_field_t list */ +struct pb_field_iter_s { + const pb_field_t *start; /* Start of the pb_field_t array */ + const pb_field_t *pos; /* Current position of the iterator */ + unsigned required_field_index; /* Zero-based index that counts only the required fields */ + void *dest_struct; /* Pointer to start of the structure */ + void *pData; /* Pointer to current field value */ + void *pSize; /* Pointer to count/has field */ +}; +typedef struct pb_field_iter_s pb_field_iter_t; + /* Initialize the field iterator structure to beginning. * Returns false if the message type is empty. */ -bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message); - -/* Get a field iterator for extension field. */ -bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension); - -/* Same as pb_field_iter_begin(), but for const message pointer. - * Note that the pointers in pb_field_iter_t will be non-const but shouldn't - * be written to when using these functions. */ -bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message); -bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension); +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); /* Advance the iterator to the next field. * Returns false when the iterator wraps back to the first field. */ @@ -32,11 +34,6 @@ bool pb_field_iter_next(pb_field_iter_t *iter); * Returns false if no such field exists. */ bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); -#ifdef PB_VALIDATE_UTF8 -/* Validate UTF-8 text string */ -bool pb_validate_utf8(const char *s); -#endif - #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/ui/nanopb/pb_decode.c b/src/ui/nanopb/pb_decode.c index f936412b..17cc3e9c 100644 --- a/src/ui/nanopb/pb_decode.c +++ b/src/ui/nanopb/pb_decode.c @@ -17,38 +17,43 @@ #include "pb_decode.h" #include "pb_common.h" +#include "os.h" + /************************************** * Declarations internal to this file * **************************************/ +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); -static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof); static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); -static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field); -static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field); -static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); -static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); -static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field); +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool inline checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) __attribute__((no_instrument_function)); +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); static bool checkreturn find_extension_field(pb_field_iter_t *iter); -static bool pb_message_set_to_defaults(pb_field_iter_t *iter); -static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field); +static void pb_field_set_to_default(pb_field_iter_t *iter); +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool inline checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) __attribute__((no_instrument_function)); +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); static bool checkreturn pb_skip_varint(pb_istream_t *stream); static bool checkreturn pb_skip_string(pb_istream_t *stream); #ifdef PB_ENABLE_MALLOC static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); -static void initialize_pointer_field(void *pItem, pb_field_iter_t *field); -static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field); -static void pb_release_single_field(pb_field_iter_t *field); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); +static void pb_release_single_field(const pb_field_iter_t *iter); +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter); #endif #ifdef PB_WITHOUT_64BIT @@ -59,9 +64,121 @@ static void pb_release_single_field(pb_field_iter_t *field); #define pb_uint64_t uint64_t #endif -typedef struct { - uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32]; -} pb_fields_seen_t; +/* --- Function pointers to field decoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { + &pb_dec_varint, + &pb_dec_uvarint, + &pb_dec_svarint, + &pb_dec_fixed32, + &pb_dec_fixed64, + + &pb_dec_bytes, + &pb_dec_string, + &pb_dec_submessage, + NULL, /* extensions */ + &pb_dec_fixed_length_bytes +}; + +extern void _ebss; +extern void _estack; +int G_depth; +int last_stack_left; +typedef struct addr_to_fname_s { + const void* const addr; + const char* const name; +} addr_to_fname_t; + +static bool checkreturn inline decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) __attribute__((no_instrument_function)); +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf); + +const addr_to_fname_t addr_to_fnames[] = { + { pb_readbyte, "pb_readbyte" }, + { decode_pointer_field, "decode_pointer_field" }, +#ifdef PB_ENABLE_MALLOC + { initialize_pointer_field, "initialize_pointer_field" }, + { allocate_field, "allocate_field" }, + { pb_release_union_field, "pb_release_union_field" }, + { pb_release_single_field, "pb_release_single_field" }, + { pb_release, "pb_release" }, +#endif + { pb_decode, "pb_decode" }, + { pb_message_set_to_defaults, "pb_message_set_to_defaults" }, + { pb_decode_noinit, "pb_decode_noinit" }, + { buf_read, "buf_read" }, + { read_raw_value, "read_raw_value" }, + { decode_static_field, "decode_static_field" }, + { decode_callback_field, "decode_callback_field" }, + { decode_field, "decode_field" }, + { iter_from_extension, "iter_from_extension" }, + { default_extension_decoder, "default_extension_decoder" }, + { decode_extension, "decode_extension" }, + { find_extension_field, "find_extension_field" }, + { pb_field_set_to_default, "pb_field_set_to_default" }, + { pb_message_set_to_defaults, "pb_message_set_to_defaults" }, + { pb_dec_varint, "pb_dec_varint" }, + { pb_decode_varint32_eof, "pb_decode_varint32_eof" }, + { pb_dec_uvarint, "pb_dec_uvarint" }, + { pb_dec_svarint, "pb_dec_svarint" }, + { pb_dec_fixed32, "pb_dec_fixed32" }, + { pb_dec_fixed64, "pb_dec_fixed64" }, + { pb_dec_bytes, "pb_dec_bytes" }, + { pb_dec_string, "pb_dec_string" }, + { pb_dec_submessage, "pb_dec_submessage" }, + { pb_dec_fixed_length_bytes, "pb_dec_fixed_length_bytes" }, + { pb_skip_varint, "pb_skip_varint" }, + { pb_skip_string, "pb_skip_string" }, + { pb_decode_delimited, "pb_decode_delimited" }, + { pb_decode_delimited_noinit, "pb_decode_delimited_noinit" }, + { pb_decode_nullterminated, "pb_decode_nullterminated" }, + { pb_istream_from_buffer, "pb_istream_from_buffer" }, + { pb_read, "pb_read" }, + { pb_decode_tag, "pb_decode_tag" }, + { pb_skip_field, "pb_skip_field" }, + // { pb_decode_varint, "pb_decode_varint" }, + { pb_decode_varint32, "pb_decode_varint32" }, + { pb_decode_svarint, "pb_decode_svarint" }, + { pb_decode_fixed32, "pb_decode_fixed32" }, + { pb_make_string_substream, "pb_make_string_substream" }, + { pb_close_string_substream, "pb_close_string_substream" }, + { decode_pointer_field, "decode_pointer_field" }, + { decode_callback_field, "decode_callback_field" } +}; + +const char* addr_to_fname(void* func) __attribute__((no_instrument_function)); +const char* addr_to_fname(void* func){ + for(int i = 0; i < sizeof(addr_to_fnames)/sizeof(*addr_to_fnames); i++){ + if(PIC(addr_to_fnames[i].addr) == func){ + return (const char*)(PIC(addr_to_fnames[i].name)); + } + } + return ""; +} + +void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function)); +void __cyg_profile_func_enter( void *func, void *callsite ) +{ + const char* fname = addr_to_fname(func); + for(int i = 0; i < G_depth; i++){ + PRINTF(" "); + } + PRINTF("-> %p '%s' [from %p], STACK %p, left: %d\n", func, fname, callsite, &fname, ((void*)&fname) - &_ebss); //, last_stack_left - (((void*)&fname) - &_ebss)); + last_stack_left = ((void*)&fname) - &_ebss; + G_depth++; +} +void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function)); +void __cyg_profile_func_exit( void *func, void *callsite ) +{ + const char* fname = addr_to_fname(func); + // last_stack_left = ((void*)&fname) - &_ebss; + G_depth--; + for(int i = 0; i < G_depth; i++){ + PRINTF(" "); + } + PRINTF("<- %p '%s' [from %p], left: %d\n", func, fname, callsite, ((void*)&fname) - &_ebss); + // last_stack_left = ((void*)&fname) - &_ebss; +} /******************************* * pb_istream_t implementation * @@ -84,9 +201,6 @@ static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t co bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { - if (count == 0) - return true; - #ifndef PB_BUFFER_ONLY if (buf == NULL && stream->callback != buf_read) { @@ -204,7 +318,7 @@ static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *d if (bitpos >= 32) { /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ - pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) { @@ -248,7 +362,6 @@ bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) if (!pb_readbyte(stream, &byte)) return false; - result |= (uint64_t)(byte & 0x7F) << bitpos; bitpos = (uint_fast8_t)(bitpos + 7); } while (byte & 0x80); @@ -275,12 +388,7 @@ bool checkreturn pb_skip_string(pb_istream_t *stream) if (!pb_decode_varint32(stream, &length)) return false; - if ((size_t)length != length) - { - PB_RETURN_ERROR(stream, "size too large"); - } - - return pb_read(stream, NULL, (size_t)length); + return pb_read(stream, NULL, length); } bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) @@ -295,8 +403,15 @@ bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, return false; } + if (temp == 0) + { + *eof = true; /* Special feature: allow 0-terminated messages. */ + return false; + } + *tag = temp >> 3; *wire_type = (pb_wire_type_t)(temp & 7); + return true; } @@ -325,11 +440,8 @@ static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire do { (*size)++; - if (*size > max_size) - PB_RETURN_ERROR(stream, "varint overflow"); - - if (!pb_read(stream, buf, 1)) - return false; + if (*size > max_size) return false; + if (!pb_read(stream, buf, 1)) return false; } while (*buf++ & 0x80); return true; @@ -341,12 +453,6 @@ static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire *size = 4; return pb_read(stream, buf, 4); - case PB_WT_STRING: - /* Calling read_raw_value with a PB_WT_STRING is an error. - * Explicitly handle this case and fallthrough to default to avoid - * compiler warnings. - */ - default: PB_RETURN_ERROR(stream, "invalid wire_type"); } } @@ -364,8 +470,8 @@ bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *su if (substream->bytes_left < size) PB_RETURN_ERROR(stream, "parent stream too short"); - substream->bytes_left = (size_t)size; - stream->bytes_left -= (size_t)size; + substream->bytes_left = size; + stream->bytes_left -= size; return true; } @@ -388,108 +494,46 @@ bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *s * Decode a single field * *************************/ -static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field) -{ - switch (PB_LTYPE(field->type)) - { - case PB_LTYPE_BOOL: - case PB_LTYPE_VARINT: - case PB_LTYPE_UVARINT: - case PB_LTYPE_SVARINT: - return wire_type == PB_WT_VARINT; - - case PB_LTYPE_FIXED32: - return wire_type == PB_WT_32BIT; - - case PB_LTYPE_FIXED64: - return wire_type == PB_WT_64BIT; - - case PB_LTYPE_BYTES: - case PB_LTYPE_STRING: - case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_SUBMSG_W_CB: - case PB_LTYPE_FIXED_LENGTH_BYTES: - return wire_type == PB_WT_STRING; - - default: - return false; - } -} - -static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field) +pb_type_t type; +pb_decoder_t func; +static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { - switch (PB_LTYPE(field->type)) - { - case PB_LTYPE_BOOL: - return pb_dec_bool(stream, field); - - case PB_LTYPE_VARINT: - case PB_LTYPE_UVARINT: - case PB_LTYPE_SVARINT: - return pb_dec_varint(stream, field); - - case PB_LTYPE_FIXED32: - case PB_LTYPE_FIXED64: - return pb_dec_fixed(stream, field); - - case PB_LTYPE_BYTES: - return pb_dec_bytes(stream, field); - - case PB_LTYPE_STRING: - return pb_dec_string(stream, field); - - case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_SUBMSG_W_CB: - return pb_dec_submessage(stream, field); - - case PB_LTYPE_FIXED_LENGTH_BYTES: - return pb_dec_fixed_length_bytes(stream, field); - - default: - PB_RETURN_ERROR(stream, "invalid field type"); - } -} - -static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) -{ - switch (PB_HTYPE(field->type)) + type = ((const pb_field_t *)PIC(iter->pos))->type; + func = (pb_decoder_t)PIC(PB_DECODERS[PB_LTYPE(type)]); + + switch (PB_HTYPE(type)) { case PB_HTYPE_REQUIRED: - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - return decode_basic_field(stream, field); + return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); case PB_HTYPE_OPTIONAL: - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - if (field->pSize != NULL) - *(bool*)field->pSize = true; - return decode_basic_field(stream, field); + if (iter->pSize != iter->pData) + *(bool*)iter->pSize = true; + return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); case PB_HTYPE_REPEATED: if (wire_type == PB_WT_STRING - && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) { +#ifndef PROTO2_SUPPORT + return false; +#else /* Packed array */ bool status = true; + pb_size_t *size = (pb_size_t*)iter->pSize; pb_istream_t substream; - pb_size_t *size = (pb_size_t*)field->pSize; - field->pData = (char*)field->pField + field->data_size * (*size); - if (!pb_make_string_substream(stream, &substream)) return false; - - while (substream.bytes_left > 0 && *size < field->array_size) + + while (substream.bytes_left > 0 && *size < ((const pb_field_t *)PIC(iter->pos))->array_size) { - if (!decode_basic_field(&substream, field)) + void *pItem = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); + if (!func(&substream, ((const pb_field_t *)PIC(iter->pos)), pItem)) { status = false; break; } (*size)++; - field->pData = (char*)field->pData + field->data_size; } if (substream.bytes_left != 0) @@ -498,40 +542,30 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t return false; return status; +#endif } else { /* Repeated field */ - pb_size_t *size = (pb_size_t*)field->pSize; - field->pData = (char*)field->pField + field->data_size * (*size); - - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - if ((*size)++ >= field->array_size) + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); + if (*size >= ((const pb_field_t *)PIC(iter->pos))->array_size) PB_RETURN_ERROR(stream, "array overflow"); - - return decode_basic_field(stream, field); + + (*size)++; + return func(stream, ((const pb_field_t *)PIC(iter->pos)), pItem); } case PB_HTYPE_ONEOF: - *(pb_size_t*)field->pSize = field->tag; - if (PB_LTYPE_IS_SUBMSG(field->type)) + *(pb_size_t*)iter->pSize = ((const pb_field_t *)PIC(iter->pos))->tag; + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { /* We memset to zero so that any callbacks are set to NULL. - * This is because the callbacks might otherwise have values - * from some other union field. - * If callbacks are needed inside oneof field, use .proto - * option submsg_callback to have a separate callback function - * that can set the fields before submessage is decoded. - * pb_dec_submessage() will set any default values. */ - memset(field->pData, 0, (size_t)field->data_size); + * Then set any default values. */ + memset(iter->pData, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); + pb_message_set_to_defaults((const pb_field_t*)((const pb_field_t *)PIC(iter->pos))->ptr, iter->pData); } - - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - return decode_basic_field(stream, field); + return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); default: PB_RETURN_ERROR(stream, "invalid field type"); @@ -550,16 +584,6 @@ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t if (data_size == 0 || array_size == 0) PB_RETURN_ERROR(stream, "invalid size"); -#ifdef __AVR__ - /* Workaround for AVR libc bug 53284: http://savannah.nongnu.org/bugs/?53284 - * Realloc to size of 1 byte can cause corruption of the malloc structures. - */ - if (data_size == 1 && array_size == 1) - { - data_size = 2; - } -#endif - /* Check for multiplication overflows. * This code avoids the costly division if the sizes are small enough. * Multiplication is safe as long as only half of bits are set @@ -583,86 +607,86 @@ static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t ptr = pb_realloc(ptr, array_size * data_size); if (ptr == NULL) PB_RETURN_ERROR(stream, "realloc failed"); - *(void**)pData = ptr; return true; } /* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ -static void initialize_pointer_field(void *pItem, pb_field_iter_t *field) +static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) { - if (PB_LTYPE(field->type) == PB_LTYPE_STRING || - PB_LTYPE(field->type) == PB_LTYPE_BYTES) + if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_STRING || + PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_BYTES) { *(void**)pItem = NULL; } - else if (PB_LTYPE_IS_SUBMSG(field->type)) + else if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_SUBMESSAGE) { /* We memset to zero so that any callbacks are set to NULL. * Then set any default values. */ - pb_field_iter_t submsg_iter; - memset(pItem, 0, field->data_size); + memset(pItem, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); - if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, pItem)) - { - (void)pb_message_set_to_defaults(&submsg_iter); - } + pb_message_set_to_defaults((const pb_field_t *) ((const pb_field_t *)PIC(iter->pos))->ptr, pItem); } } #endif -static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { #ifndef PB_ENABLE_MALLOC PB_UNUSED(wire_type); - PB_UNUSED(field); + PB_UNUSED(iter); PB_RETURN_ERROR(stream, "no malloc support"); #else - switch (PB_HTYPE(field->type)) + pb_type_t type; + pb_decoder_t func; + + type = ((const pb_field_t *)PIC(iter->pos))->type; + func = PIC(PB_DECODERS[PB_LTYPE(type)]); + + switch (PB_HTYPE(type)) { case PB_HTYPE_REQUIRED: case PB_HTYPE_OPTIONAL: case PB_HTYPE_ONEOF: - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL) + if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && + *(void**)iter->pData != NULL) { + // if an error has been observed, no need to release memory + if(stream->errmsg){ + return false; + } /* Duplicate field, have to release the old allocation first. */ - /* FIXME: Does this work correctly for oneofs? */ - pb_release_single_field(field); + pb_release_single_field(iter); } - if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { - *(pb_size_t*)field->pSize = field->tag; + *(pb_size_t*)iter->pSize = ((const pb_field_t *)PIC(iter->pos))->tag; } - if (PB_LTYPE(field->type) == PB_LTYPE_STRING || - PB_LTYPE(field->type) == PB_LTYPE_BYTES) + if (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES) { - /* pb_dec_string and pb_dec_bytes handle allocation themselves */ - field->pData = field->pField; - return decode_basic_field(stream, field); + return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); } else { - if (!allocate_field(stream, field->pField, field->data_size, 1)) + if (!allocate_field(stream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, 1)) return false; - field->pData = *(void**)field->pField; - initialize_pointer_field(field->pData, field); - return decode_basic_field(stream, field); + initialize_pointer_field(*(void**)iter->pData, iter); + return func(stream, ((const pb_field_t *)PIC(iter->pos)), *(void**)iter->pData); } case PB_HTYPE_REPEATED: if (wire_type == PB_WT_STRING - && PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) + && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) { /* Packed array, multiple items come in at once. */ bool status = true; - pb_size_t *size = (pb_size_t*)field->pSize; + pb_size_t *size = (pb_size_t*)iter->pSize; size_t allocated_size = *size; + void *pItem; pb_istream_t substream; if (!pb_make_string_substream(stream, &substream)) @@ -670,27 +694,13 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ while (substream.bytes_left) { - if (*size == PB_SIZE_MAX) - { -#ifndef PB_NO_ERRMSG - stream->errmsg = "too many array entries"; -#endif - status = false; - break; - } - if ((size_t)*size + 1 > allocated_size) { /* Allocate more storage. This tries to guess the * number of remaining entries. Round the division * upwards. */ - size_t remain = (substream.bytes_left - 1) / field->data_size + 1; - if (remain < PB_SIZE_MAX - allocated_size) - allocated_size += remain; - else - allocated_size += 1; - - if (!allocate_field(&substream, field->pField, field->data_size, allocated_size)) + allocated_size += (substream.bytes_left - 1) / ((const pb_field_t *)PIC(iter->pos))->data_size + 1; + if (!allocate_field(&substream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, allocated_size)) { status = false; break; @@ -698,10 +708,19 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ } /* Decode the array entry */ - field->pData = *(char**)field->pField + field->data_size * (*size); - initialize_pointer_field(field->pData, field); - if (!decode_basic_field(&substream, field)) + pItem = *(char**)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); + initialize_pointer_field(pItem, iter); + if (!func(&substream, ((const pb_field_t *)PIC(iter->pos)), pItem)) + { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) { +#ifndef PB_NO_ERRMSG + stream->errmsg = "too many array entries"; +#endif status = false; break; } @@ -716,21 +735,20 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ else { /* Normal repeated field, i.e. only one item at a time. */ - pb_size_t *size = (pb_size_t*)field->pSize; - + pb_size_t *size = (pb_size_t*)iter->pSize; + void *pItem; + if (*size == PB_SIZE_MAX) PB_RETURN_ERROR(stream, "too many array entries"); - if (!check_wire_type(wire_type, field)) - PB_RETURN_ERROR(stream, "wrong wire type"); - - if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1))) + (*size)++; + if (!allocate_field(stream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, *size)) return false; + - field->pData = *(char**)field->pField + field->data_size * (*size); - (*size)++; - initialize_pointer_field(field->pData, field); - return decode_basic_field(stream, field); + pItem = *(char**)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size - 1); + initialize_pointer_field(pItem, iter); + return func(stream, ((const pb_field_t *)PIC(iter->pos)), pItem); } default: @@ -739,25 +757,32 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_ #endif } -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { - if (!field->descriptor->field_callback) - return pb_skip_field(stream, wire_type); + pb_callback_t *pCallback = (pb_callback_t*)iter->pData; + +#ifdef PB_OLD_CALLBACK_STYLE + void *arg = pCallback->arg; +#else + void **arg = &(pCallback->arg); +#endif + + if (pCallback == NULL || pCallback->funcs.decode == NULL) + return pb_skip_field(stream, wire_type); + if (wire_type == PB_WT_STRING) { pb_istream_t substream; - size_t prev_bytes_left; if (!pb_make_string_substream(stream, &substream)) return false; do { - prev_bytes_left = substream.bytes_left; - if (!field->descriptor->field_callback(&substream, NULL, field)) + if (!pCallback->funcs.decode(&substream, ((const pb_field_t *)PIC(iter->pos)), arg)) PB_RETURN_ERROR(stream, "callback failed"); - } while (substream.bytes_left > 0 && substream.bytes_left < prev_bytes_left); + } while (substream.bytes_left); if (!pb_close_string_substream(stream, &substream)) return false; @@ -778,52 +803,69 @@ static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type return false; substream = pb_istream_from_buffer(buffer, size); - return field->descriptor->field_callback(&substream, NULL, field); + return pCallback->funcs.decode(&substream, ((const pb_field_t *)PIC(iter->pos)), arg); } } -static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field) +static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) { #ifdef PB_ENABLE_MALLOC /* When decoding an oneof field, check if there is old data that must be * released first. */ - if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + if (PB_HTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_HTYPE_ONEOF) { - if (!pb_release_union_field(stream, field)) + if (!pb_release_union_field(stream, iter)) return false; } #endif - - switch (PB_ATYPE(field->type)) + + switch (PB_ATYPE(((const pb_field_t *)PIC(iter->pos))->type)) { case PB_ATYPE_STATIC: - return decode_static_field(stream, wire_type, field); + return decode_static_field(stream, wire_type, iter); case PB_ATYPE_POINTER: - return decode_pointer_field(stream, wire_type, field); + return decode_pointer_field(stream, wire_type, iter); case PB_ATYPE_CALLBACK: - return decode_callback_field(stream, wire_type, field); + return decode_callback_field(stream, wire_type, iter); default: PB_RETURN_ERROR(stream, "invalid field type"); } } -/* Default handler for extension fields. Expects to have a pb_msgdesc_t - * pointer in the extension->type->arg field, pointing to a message with - * only one field in it. */ +static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) +{ + /* Fake a field iterator for the extension field. + * It is not actually safe to advance this iterator, but decode_field + * will not even try to. */ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + (void)pb_field_iter_begin(iter, field, extension->dest); + iter->pData = extension->dest; + iter->pSize = &extension->found; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + iter->pData = &extension->dest; + } +} + +/* Default handler for extension fields. Expects a pb_field_t structure + * in extension->type->arg. */ static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) { + const pb_field_t *field = (const pb_field_t*)extension->type->arg; pb_field_iter_t iter; - - if (!pb_field_iter_begin_extension(&iter, extension)) - PB_RETURN_ERROR(stream, "invalid extension"); - - if (iter.tag != tag) + + if (field->tag != tag) return true; - + + iter_from_extension(&iter, extension); extension->found = true; return decode_field(stream, wire_type, &iter); } @@ -858,165 +900,122 @@ static bool checkreturn decode_extension(pb_istream_t *stream, * message. Returns false if no extension field is found. */ static bool checkreturn find_extension_field(pb_field_iter_t *iter) { - pb_size_t start = iter->index; - + const pb_field_t *start = (const pb_field_t *)PIC(iter->pos); + do { - if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) + if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_EXTENSION) return true; (void)pb_field_iter_next(iter); - } while (iter->index != start); + } while (((const pb_field_t *)PIC(iter->pos)) != start); return false; } /* Initialize message fields to default values, recursively */ -static bool pb_field_set_to_default(pb_field_iter_t *field) +static void pb_field_set_to_default(pb_field_iter_t *iter) { pb_type_t type; - type = field->type; - + type = ((const pb_field_t *)PIC(iter->pos))->type; if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { - pb_extension_t *ext = *(pb_extension_t* const *)field->pData; + pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; while (ext != NULL) { pb_field_iter_t ext_iter; - if (pb_field_iter_begin_extension(&ext_iter, ext)) - { - ext->found = false; - if (!pb_message_set_to_defaults(&ext_iter)) - return false; - } + ext->found = false; + iter_from_extension(&ext_iter, ext); + pb_field_set_to_default(&ext_iter); ext = ext->next; } } else if (PB_ATYPE(type) == PB_ATYPE_STATIC) { bool init_data = true; - if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) { /* Set has_field to false. Still initialize the optional field * itself also. */ - *(bool*)field->pSize = false; + *(bool*)iter->pSize = false; } else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || PB_HTYPE(type) == PB_HTYPE_ONEOF) { /* REPEATED: Set array count to 0, no need to initialize contents. ONEOF: Set which_field to 0. */ - *(pb_size_t*)field->pSize = 0; + *(pb_size_t*)iter->pSize = 0; init_data = false; } if (init_data) { - if (PB_LTYPE_IS_SUBMSG(field->type)) + if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_SUBMESSAGE) { /* Initialize submessage to defaults */ - pb_field_iter_t submsg_iter; - if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) - { - if (!pb_message_set_to_defaults(&submsg_iter)) - return false; - } + pb_message_set_to_defaults((const pb_field_t *) ((const pb_field_t *)PIC(iter->pos))->ptr, iter->pData); + } + else if (((const pb_field_t *)PIC(iter->pos))->ptr != NULL) + { + /* Initialize to default value */ + memcpy(iter->pData, ((const pb_field_t *)PIC(iter->pos))->ptr, ((const pb_field_t *)PIC(iter->pos))->data_size); } else { /* Initialize to zeros */ - memset(field->pData, 0, (size_t)field->data_size); + memset(iter->pData, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); } } } else if (PB_ATYPE(type) == PB_ATYPE_POINTER) - { + { /* Initialize the pointer to NULL. */ - *(void**)field->pField = NULL; - + *(void**)iter->pData = NULL; /* Initialize array count to 0. */ if (PB_HTYPE(type) == PB_HTYPE_REPEATED || PB_HTYPE(type) == PB_HTYPE_ONEOF) { - *(pb_size_t*)field->pSize = 0; + *(pb_size_t*)iter->pSize = 0; } } else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) { /* Don't overwrite callback */ } - - return true; } -static bool pb_message_set_to_defaults(pb_field_iter_t *iter) +static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) { - pb_istream_t defstream = PB_ISTREAM_EMPTY; - uint32_t tag = 0; - pb_wire_type_t wire_type = PB_WT_VARINT; - bool eof; - - if (iter->descriptor->default_value) - { - defstream = pb_istream_from_buffer(iter->descriptor->default_value, (size_t)-1); - if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) - return false; - } - + pb_field_iter_t iter; + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ do { - if (!pb_field_set_to_default(iter)) - return false; - - if (tag != 0 && iter->tag == tag) - { - /* We have a default value for this field in the defstream */ - if (!decode_field(&defstream, wire_type, iter)) - return false; - if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) - return false; - - if (iter->pSize) - *(bool*)iter->pSize = false; - } - } while (pb_field_iter_next(iter)); - - return true; + pb_field_set_to_default(&iter); + } while (pb_field_iter_next(&iter)); } /********************* * Decode all fields * *********************/ - -static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +#define PB_DECODE_STACK_REQUIREMENT 260 +bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { - uint32_t extension_range_start = 0; + if(check_stack_overflow(PB_DECODE_STACK_REQUIREMENT)) + PB_RETURN_ERROR(stream, "not enough stack"); - /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed - * count field. This can only handle _one_ repeated fixed count field that - * is unpacked and unordered among other (non repeated fixed count) fields. - */ - pb_size_t fixed_count_field = PB_SIZE_MAX; - pb_size_t fixed_count_size = 0; - pb_size_t fixed_count_total_size = 0; - - pb_fields_seen_t fields_seen = {{0, 0}}; - const uint32_t allbits = ~(uint32_t)0; + // uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; + // const uint32_t allbits = ~(uint32_t)0; + // uint32_t extension_range_start = 0; pb_field_iter_t iter; - - if (pb_field_iter_begin(&iter, fields, dest_struct)) - { - if ((flags & PB_DECODE_NOINIT) == 0) - { - if (!pb_message_set_to_defaults(&iter)) - PB_RETURN_ERROR(stream, "failed to set defaults"); - } - } - + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); while (stream->bytes_left) { uint32_t tag; pb_wire_type_t wire_type; bool eof; - if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { if (eof) @@ -1024,110 +1023,70 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t else return false; } - - if (tag == 0) + if (!pb_field_iter_find(&iter, tag)) { - if (flags & PB_DECODE_NULLTERMINATED) - { - break; - } - else - { - PB_RETURN_ERROR(stream, "zero tag"); - } - } - if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) - { +#ifdef PROTO2_SUPPORT /* No match found, check if it matches an extension. */ if (tag >= extension_range_start) { if (!find_extension_field(&iter)) extension_range_start = (uint32_t)-1; else - extension_range_start = iter.tag; - + extension_range_start = ((const pb_field_t*)PIC(iter.pos))->tag; + if (tag >= extension_range_start) { size_t pos = stream->bytes_left; - + if (!decode_extension(stream, tag, wire_type, &iter)) return false; - + if (pos != stream->bytes_left) { /* The field was handled */ - continue; + continue; } } } - +#endif /* No match found, skip data */ if (!pb_skip_field(stream, wire_type)) return false; continue; } - /* If a repeated fixed count field was found, get size from - * 'fixed_count_field' as there is no counter contained in the struct. - */ - if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED && iter.pSize == &iter.array_size) - { - if (fixed_count_field != iter.index) { - /* If the new fixed count field does not match the previous one, - * check that the previous one is NULL or that it finished - * receiving all the expected data. - */ - if (fixed_count_field != PB_SIZE_MAX && - fixed_count_size != fixed_count_total_size) - { - PB_RETURN_ERROR(stream, "wrong size for fixed count field"); - } - - fixed_count_field = iter.index; - fixed_count_size = 0; - fixed_count_total_size = iter.array_size; - } - - iter.pSize = &fixed_count_size; - } - - if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED +#ifdef PROTO2_SUPPORT + if (PB_HTYPE(((const pb_field_t*)PIC(iter.pos))->type) == PB_HTYPE_REQUIRED && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); - fields_seen.bitfield[iter.required_field_index >> 5] |= tmp; + fields_seen[iter.required_field_index >> 5] |= tmp; } - +#endif if (!decode_field(stream, wire_type, &iter)) return false; } - /* Check that all elements of the last decoded fixed count field were present. */ - if (fixed_count_field != PB_SIZE_MAX && - fixed_count_size != fixed_count_total_size) - { - PB_RETURN_ERROR(stream, "wrong size for fixed count field"); - } - +#ifdef PROTO2_SUPPORT /* Check that all required fields were present. */ { /* First figure out the number of required fields by * seeking to the end of the field array. Usually we * are already close to end after decoding. */ - pb_size_t req_field_count; + unsigned req_field_count; pb_type_t last_type; - pb_size_t i; + unsigned i; do { req_field_count = iter.required_field_index; - last_type = iter.type; + last_type = ((const pb_field_t*)PIC(iter.pos))->type; } while (pb_field_iter_next(&iter)); - + /* Fixup if last field was also required. */ - if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.tag != 0) + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && ((const pb_field_t*)PIC(iter.pos))->tag != 0) req_field_count++; - + if (req_field_count > PB_MAX_REQUIRED_FIELDS) req_field_count = PB_MAX_REQUIRED_FIELDS; @@ -1136,75 +1095,86 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t /* Check the whole words */ for (i = 0; i < (req_field_count >> 5); i++) { - if (fields_seen.bitfield[i] != allbits) + if (fields_seen[i] != allbits) PB_RETURN_ERROR(stream, "missing required field"); } - + /* Check the remaining bits (if any) */ if ((req_field_count & 31) != 0) { - if (fields_seen.bitfield[req_field_count >> 5] != - (allbits >> (uint_least8_t)(32 - (req_field_count & 31)))) + if (fields_seen[req_field_count >> 5] != + (allbits >> (32 - (req_field_count & 31)))) { PB_RETURN_ERROR(stream, "missing required field"); } } } } +#endif return true; } -bool checkreturn pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags) +bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { bool status; - - if ((flags & PB_DECODE_DELIMITED) == 0) - { - status = pb_decode_inner(stream, fields, dest_struct, flags); - } - else - { - pb_istream_t substream; - if (!pb_make_string_substream(stream, &substream)) - return false; - - status = pb_decode_inner(&substream, fields, dest_struct, flags); - - if (!pb_close_string_substream(stream, &substream)) - return false; - } - + pb_message_set_to_defaults(fields, dest_struct); + status = pb_decode_noinit(stream, fields, dest_struct); +/* #ifdef PB_ENABLE_MALLOC if (!status) pb_release(fields, dest_struct); #endif - +*/ return status; } -bool checkreturn pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct) +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) { + pb_istream_t substream; bool status; - status = pb_decode_inner(stream, fields, dest_struct, 0); + if (!pb_make_string_substream(stream, &substream)) + return false; + status = pb_decode_noinit(&substream, fields, dest_struct); -#ifdef PB_ENABLE_MALLOC - if (!status) - pb_release(fields, dest_struct); -#endif + if (!pb_close_string_substream(stream, &substream)) + return false; + return status; +} +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + pb_istream_t substream; + bool status; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + status = pb_decode(&substream, fields, dest_struct); + + if (!pb_close_string_substream(stream, &substream)) + return false; return status; } +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) +{ + /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ + return pb_decode(stream, fields, dest_struct); +} + #ifdef PB_ENABLE_MALLOC /* Given an oneof field, if there has already been a field inside this oneof, * release it before overwriting with a different one. */ -static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field) +static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) { - pb_field_iter_t old_field = *field; - pb_size_t old_tag = *(pb_size_t*)field->pSize; /* Previous which_ value */ - pb_size_t new_tag = field->tag; /* New which_ value */ + // if an error has been observed, no need to release memory + if(stream->errmsg){ + return false; + } + pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ + pb_size_t new_tag = ((const pb_field_t *)PIC(iter->pos))->tag; /* New which_ value */ if (old_tag == 0) return true; /* Ok, no old data in union */ @@ -1214,22 +1184,27 @@ static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *field) /* Release old data. The find can fail if the message struct contains * invalid data. */ - if (!pb_field_iter_find(&old_field, old_tag)) + if (!pb_field_iter_find(iter, old_tag)) PB_RETURN_ERROR(stream, "invalid union tag"); - pb_release_single_field(&old_field); + pb_release_single_field(iter); + /* Restore iterator to where it should be. + * This shouldn't fail unless the pb_field_t structure is corrupted. */ + if (!pb_field_iter_find(iter, new_tag)) + PB_RETURN_ERROR(stream, "iterator error"); + return true; } -static void pb_release_single_field(pb_field_iter_t *field) +static void pb_release_single_field(const pb_field_iter_t *iter) { pb_type_t type; - type = field->type; + type = ((const pb_field_t *)PIC(iter->pos))->type; if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { - if (*(pb_size_t*)field->pSize != field->tag) + if (*(pb_size_t*)iter->pSize != ((const pb_field_t *)PIC(iter->pos))->tag) return; /* This is not the current field in the union */ } @@ -1239,48 +1214,43 @@ static void pb_release_single_field(pb_field_iter_t *field) if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { /* Release fields from all extensions in the linked list */ - pb_extension_t *ext = *(pb_extension_t**)field->pData; + pb_extension_t *ext = *(pb_extension_t**)iter->pData; while (ext != NULL) { pb_field_iter_t ext_iter; - if (pb_field_iter_begin_extension(&ext_iter, ext)) - { - pb_release_single_field(&ext_iter); - } + iter_from_extension(&ext_iter, ext); + pb_release_single_field(&ext_iter); ext = ext->next; } } - else if (PB_LTYPE_IS_SUBMSG(type) && PB_ATYPE(type) != PB_ATYPE_CALLBACK) + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { /* Release fields in submessage or submsg array */ + void *pItem = iter->pData; pb_size_t count = 1; if (PB_ATYPE(type) == PB_ATYPE_POINTER) { - field->pData = *(void**)field->pField; - } - else - { - field->pData = field->pField; + pItem = *(void**)iter->pData; } if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { - count = *(pb_size_t*)field->pSize; + count = *(pb_size_t*)iter->pSize; - if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > field->array_size) + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > ((const pb_field_t *)PIC(iter->pos))->array_size) { /* Protect against corrupted _count fields */ - count = field->array_size; + count = ((const pb_field_t *)PIC(iter->pos))->array_size; } } - if (field->pData) + if (pItem) { while (count--) { - pb_release(field->submsg_desc, field->pData); - field->pData = (char*)field->pData + field->data_size; + pb_release((const pb_field_t*)((const pb_field_t *)PIC(iter->pos))->ptr, pItem); + pItem = (char*)pItem + ((const pb_field_t *)PIC(iter->pos))->data_size; } } } @@ -1292,8 +1262,8 @@ static void pb_release_single_field(pb_field_iter_t *field) PB_LTYPE(type) == PB_LTYPE_BYTES)) { /* Release entries in repeated string or bytes array */ - void **pItem = *(void***)field->pField; - pb_size_t count = *(pb_size_t*)field->pSize; + void **pItem = *(void***)iter->pData; + pb_size_t count = *(pb_size_t*)iter->pSize; while (count--) { pb_free(*pItem); @@ -1304,16 +1274,16 @@ static void pb_release_single_field(pb_field_iter_t *field) if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { /* We are going to release the array, so set the size to 0 */ - *(pb_size_t*)field->pSize = 0; + *(pb_size_t*)iter->pSize = 0; } - /* Release main pointer */ - pb_free(*(void**)field->pField); - *(void**)field->pField = NULL; + /* Release main item */ + pb_free(*(void**)iter->pData); + *(void**)iter->pData = NULL; } } -void pb_release(const pb_msgdesc_t *fields, void *dest_struct) +void pb_release(const pb_field_t fields[], void *dest_struct) { pb_field_iter_t iter; @@ -1332,16 +1302,6 @@ void pb_release(const pb_msgdesc_t *fields, void *dest_struct) /* Field decoders */ -bool pb_decode_bool(pb_istream_t *stream, bool *dest) -{ - uint32_t value; - if (!pb_decode_varint32(stream, &value)) - return false; - - *(bool*)dest = (value != 0); - return true; -} - bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) { pb_uint64_t value; @@ -1358,161 +1318,145 @@ bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) bool pb_decode_fixed32(pb_istream_t *stream, void *dest) { - union { - uint32_t fixed32; - pb_byte_t bytes[4]; - } u; + pb_byte_t bytes[4]; - if (!pb_read(stream, u.bytes, 4)) + if (!pb_read(stream, bytes, 4)) return false; - -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 - /* fast path - if we know that we're on little endian, assign directly */ - *(uint32_t*)dest = u.fixed32; -#else - *(uint32_t*)dest = ((uint32_t)u.bytes[0] << 0) | - ((uint32_t)u.bytes[1] << 8) | - ((uint32_t)u.bytes[2] << 16) | - ((uint32_t)u.bytes[3] << 24); -#endif + + *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | + ((uint32_t)bytes[1] << 8) | + ((uint32_t)bytes[2] << 16) | + ((uint32_t)bytes[3] << 24); return true; } #ifndef PB_WITHOUT_64BIT bool pb_decode_fixed64(pb_istream_t *stream, void *dest) { - union { - uint64_t fixed64; - pb_byte_t bytes[8]; - } u; + pb_byte_t bytes[8]; - if (!pb_read(stream, u.bytes, 8)) + if (!pb_read(stream, bytes, 8)) return false; - -#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 - /* fast path - if we know that we're on little endian, assign directly */ - *(uint64_t*)dest = u.fixed64; -#else - *(uint64_t*)dest = ((uint64_t)u.bytes[0] << 0) | - ((uint64_t)u.bytes[1] << 8) | - ((uint64_t)u.bytes[2] << 16) | - ((uint64_t)u.bytes[3] << 24) | - ((uint64_t)u.bytes[4] << 32) | - ((uint64_t)u.bytes[5] << 40) | - ((uint64_t)u.bytes[6] << 48) | - ((uint64_t)u.bytes[7] << 56); -#endif + + *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | + ((uint64_t)bytes[1] << 8) | + ((uint64_t)bytes[2] << 16) | + ((uint64_t)bytes[3] << 24) | + ((uint64_t)bytes[4] << 32) | + ((uint64_t)bytes[5] << 40) | + ((uint64_t)bytes[6] << 48) | + ((uint64_t)bytes[7] << 56); + return true; } #endif - -static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) { - return pb_decode_bool(stream, (bool*)field->pData); + pb_uint64_t value=0; + pb_int64_t svalue=0; + pb_int64_t clamped=0; + if (!pb_decode_varint(stream, &value)) + return false; + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = svalue; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)svalue; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)svalue; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)svalue; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; } -static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) { - if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) - { - pb_uint64_t value, clamped; - if (!pb_decode_varint(stream, &value)) - return false; - - /* Cast to the proper field size, while checking for overflows */ - if (field->data_size == sizeof(pb_uint64_t)) - clamped = *(pb_uint64_t*)field->pData = value; - else if (field->data_size == sizeof(uint32_t)) - clamped = *(uint32_t*)field->pData = (uint32_t)value; - else if (field->data_size == sizeof(uint_least16_t)) - clamped = *(uint_least16_t*)field->pData = (uint_least16_t)value; - else if (field->data_size == sizeof(uint_least8_t)) - clamped = *(uint_least8_t*)field->pData = (uint_least8_t)value; - else - PB_RETURN_ERROR(stream, "invalid data_size"); - - if (clamped != value) - PB_RETURN_ERROR(stream, "integer too large"); - - return true; - } + pb_uint64_t value = 0, clamped = 0; + if (!pb_decode_varint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_uint64_t)) + clamped = *(pb_uint64_t*)dest = value; + else if (field->data_size == sizeof(uint32_t)) + clamped = *(uint32_t*)dest = (uint32_t)value; + else if (field->data_size == sizeof(uint_least16_t)) + clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + else if (field->data_size == sizeof(uint_least8_t)) + clamped = *(uint_least8_t*)dest = (uint_least8_t)value; else - { - pb_uint64_t value; - pb_int64_t svalue; - pb_int64_t clamped; - - if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) - { - if (!pb_decode_svarint(stream, &svalue)) - return false; - } - else - { - if (!pb_decode_varint(stream, &value)) - return false; - - /* See issue 97: Google's C++ protobuf allows negative varint values to - * be cast as int32_t, instead of the int64_t that should be used when - * encoding. Previous nanopb versions had a bug in encoding. In order to - * not break decoding of such messages, we cast <=32 bit fields to - * int32_t first to get the sign correct. - */ - if (field->data_size == sizeof(pb_int64_t)) - svalue = (pb_int64_t)value; - else - svalue = (int32_t)value; - } + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); - /* Cast to the proper field size, while checking for overflows */ - if (field->data_size == sizeof(pb_int64_t)) - clamped = *(pb_int64_t*)field->pData = svalue; - else if (field->data_size == sizeof(int32_t)) - clamped = *(int32_t*)field->pData = (int32_t)svalue; - else if (field->data_size == sizeof(int_least16_t)) - clamped = *(int_least16_t*)field->pData = (int_least16_t)svalue; - else if (field->data_size == sizeof(int_least8_t)) - clamped = *(int_least8_t*)field->pData = (int_least8_t)svalue; - else - PB_RETURN_ERROR(stream, "invalid data_size"); + return true; +} - if (clamped != svalue) - PB_RETURN_ERROR(stream, "integer too large"); +static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + pb_int64_t value, clamped; + if (!pb_decode_svarint(stream, &value)) + return false; + + /* Cast to the proper field size, while checking for overflows */ + if (field->data_size == sizeof(pb_int64_t)) + clamped = *(pb_int64_t*)dest = value; + else if (field->data_size == sizeof(int32_t)) + clamped = *(int32_t*)dest = (int32_t)value; + else if (field->data_size == sizeof(int_least16_t)) + clamped = *(int_least16_t*)dest = (int_least16_t)value; + else if (field->data_size == sizeof(int_least8_t)) + clamped = *(int_least8_t*)dest = (int_least8_t)value; + else + PB_RETURN_ERROR(stream, "invalid data_size"); - return true; - } + if (clamped != value) + PB_RETURN_ERROR(stream, "integer too large"); + + return true; } -static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) { -#ifdef PB_CONVERT_DOUBLE_FLOAT - if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) - { - return pb_decode_double_as_float(stream, (float*)field->pData); - } -#endif + PB_UNUSED(field); + return pb_decode_fixed32(stream, dest); +} - if (field->data_size == sizeof(uint32_t)) - { - return pb_decode_fixed32(stream, field->pData); - } +static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) +{ + PB_UNUSED(field); #ifndef PB_WITHOUT_64BIT - else if (field->data_size == sizeof(uint64_t)) - { - return pb_decode_fixed64(stream, field->pData); - } + return pb_decode_fixed64(stream, dest); +#else + PB_UNUSED(dest); + PB_RETURN_ERROR(stream, "no 64bit support"); #endif - else - { - PB_RETURN_ERROR(stream, "invalid data_size"); - } } -static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint32_t size; size_t alloc_size; - pb_bytes_array_t *dest; + pb_bytes_array_t *bdest; if (!pb_decode_varint32(stream, &size)) return false; @@ -1529,54 +1473,44 @@ static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t #ifndef PB_ENABLE_MALLOC PB_RETURN_ERROR(stream, "no malloc support"); #else - if (stream->bytes_left < size) - PB_RETURN_ERROR(stream, "end-of-stream"); - - if (!allocate_field(stream, field->pData, alloc_size, 1)) + if (!allocate_field(stream, dest, alloc_size, 1)) return false; - dest = *(pb_bytes_array_t**)field->pData; + bdest = *(pb_bytes_array_t**)dest; #endif } else { if (alloc_size > field->data_size) PB_RETURN_ERROR(stream, "bytes overflow"); - dest = (pb_bytes_array_t*)field->pData; + bdest = (pb_bytes_array_t*)dest; } - dest->size = (pb_size_t)size; - return pb_read(stream, dest->bytes, (size_t)size); + bdest->size = (pb_size_t)size; + return pb_read(stream, bdest->bytes, size); } -static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint32_t size; size_t alloc_size; - pb_byte_t *dest = (pb_byte_t*)field->pData; - + bool status; if (!pb_decode_varint32(stream, &size)) return false; - - if (size == (uint32_t)-1) - PB_RETURN_ERROR(stream, "size too large"); - + /* Space for null terminator */ - alloc_size = (size_t)(size + 1); - + alloc_size = size + 1; + if (alloc_size < size) PB_RETURN_ERROR(stream, "size too large"); - + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { #ifndef PB_ENABLE_MALLOC PB_RETURN_ERROR(stream, "no malloc support"); #else - if (stream->bytes_left < size) - PB_RETURN_ERROR(stream, "end-of-stream"); - - if (!allocate_field(stream, field->pData, alloc_size, 1)) + if (!allocate_field(stream, dest, alloc_size, 1)) return false; - dest = *(pb_byte_t**)field->pData; + dest = *(void**)dest; #endif } else @@ -1585,69 +1519,39 @@ static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_ PB_RETURN_ERROR(stream, "string overflow"); } - dest[size] = 0; - - if (!pb_read(stream, dest, (size_t)size)) - return false; - -#ifdef PB_VALIDATE_UTF8 - if (!pb_validate_utf8((const char*)dest)) - PB_RETURN_ERROR(stream, "invalid utf8"); -#endif - - return true; + status = pb_read(stream, (pb_byte_t*)dest, size); + *((pb_byte_t*)dest + size) = 0; + return status; } -static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) { - bool status = true; + bool status; pb_istream_t substream; - + const pb_field_t* submsg_fields = (const pb_field_t*)PIC(field->ptr); + if (!pb_make_string_substream(stream, &substream)) return false; - if (field->submsg_desc == NULL) + if (field->ptr == NULL) PB_RETURN_ERROR(stream, "invalid field descriptor"); /* New array entries need to be initialized, while required and optional * submessages have already been initialized in the top-level pb_decode. */ - if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED || - PB_HTYPE(field->type) == PB_HTYPE_ONEOF) - { - pb_field_iter_t submsg_iter; - if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) - { - if (!pb_message_set_to_defaults(&submsg_iter)) - PB_RETURN_ERROR(stream, "failed to set defaults"); - } - } - - /* Submessages can have a separate message-level callback that is called - * before decoding the message. Typically it is used to set callback fields - * inside oneofs. */ - if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) { - /* Message callback is stored right before pSize. */ - pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; - if (callback->funcs.decode) - { - status = callback->funcs.decode(&substream, field, &callback->arg); - } + status = pb_decode(&substream, submsg_fields, dest); } - - /* Now decode the submessage contents */ - if (status) + else { - status = pb_decode_inner(&substream, field->submsg_desc, field->pData, 0); + status = pb_decode_noinit(&substream, submsg_fields, dest); } - if (!pb_close_string_substream(stream, &substream)) return false; - return status; } -static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) { uint32_t size; @@ -1660,76 +1564,12 @@ static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb if (size == 0) { /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ - memset(field->pData, 0, (size_t)field->data_size); + memset(dest, 0, field->data_size); return true; } if (size != field->data_size) PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); - return pb_read(stream, (pb_byte_t*)field->pData, (size_t)field->data_size); -} - -#ifdef PB_CONVERT_DOUBLE_FLOAT -bool pb_decode_double_as_float(pb_istream_t *stream, float *dest) -{ - uint_least8_t sign; - int exponent; - uint32_t mantissa; - uint64_t value; - union { float f; uint32_t i; } out; - - if (!pb_decode_fixed64(stream, &value)) - return false; - - /* Decompose input value */ - sign = (uint_least8_t)((value >> 63) & 1); - exponent = (int)((value >> 52) & 0x7FF) - 1023; - mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ - - /* Figure if value is in range representable by floats. */ - if (exponent == 1024) - { - /* Special value */ - exponent = 128; - } - else if (exponent > 127) - { - /* Too large, convert to infinity */ - exponent = 128; - mantissa = 0; - } - else if (exponent < -150) - { - /* Too small, convert to zero */ - exponent = -127; - mantissa = 0; - } - else if (exponent < -126) - { - /* Denormalized */ - mantissa |= 0x1000000; - mantissa >>= (-126 - exponent); - exponent = -127; - } - - /* Round off mantissa */ - mantissa = (mantissa + 1) >> 1; - - /* Check if mantissa went over 2.0 */ - if (mantissa & 0x800000) - { - exponent += 1; - mantissa &= 0x7FFFFF; - mantissa >>= 1; - } - - /* Combine fields */ - out.i = mantissa; - out.i |= (uint32_t)(exponent + 127) << 23; - out.i |= (uint32_t)sign << 31; - - *dest = out.f; - return true; + return pb_read(stream, (pb_byte_t*)dest, field->data_size); } -#endif diff --git a/src/ui/nanopb/pb_decode.h b/src/ui/nanopb/pb_decode.h index b64d95ae..5fcc201b 100644 --- a/src/ui/nanopb/pb_decode.h +++ b/src/ui/nanopb/pb_decode.h @@ -12,6 +12,10 @@ extern "C" { #endif +/* Tracks call stack when instrumentation is enabled + * Should be set to 0 when instantiating pb_istream_t*/ +extern int G_depth; + /* Structure for defining custom input streams. You will need to provide * a callback function to read the bytes from your storage, which can be * for example a file or a network socket. @@ -45,11 +49,6 @@ struct pb_istream_s #endif }; -#ifndef PB_NO_ERRMSG -#define PB_ISTREAM_EMPTY {0,0,0,0} -#else -#define PB_ISTREAM_EMPTY {0,0,0} -#endif /*************************** * Main decoding functions * @@ -71,51 +70,46 @@ struct pb_istream_s * stream = pb_istream_from_buffer(buffer, count); * pb_decode(&stream, MyMessage_fields, &msg); */ -bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct); +bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); -/* Extended version of pb_decode, with several options to control - * the decoding process: +/* Same as pb_decode, except does not initialize the destination structure + * to default values. This is slightly faster if you need no default values + * and just do memset(struct, 0, sizeof(struct)) yourself. * - * PB_DECODE_NOINIT: Do not initialize the fields to default values. - * This is slightly faster if you do not need the default - * values and instead initialize the structure to 0 using - * e.g. memset(). This can also be used for merging two - * messages, i.e. combine already existing data with new - * values. + * This can also be used for 'merging' two messages, i.e. update only the + * fields that exist in the new message. * - * PB_DECODE_DELIMITED: Input message starts with the message size as varint. - * Corresponds to parseDelimitedFrom() in Google's - * protobuf API. - * - * PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows - * reading null terminated messages. - * NOTE: Until nanopb-0.4.0, pb_decode() also allows - * null-termination. This behaviour is not supported in - * most other protobuf implementations, so PB_DECODE_DELIMITED - * is a better option for compatibility. - * - * Multiple flags can be combined with bitwise or (| operator) + * Note: If this function returns with an error, it will not release any + * dynamically allocated fields. You will need to call pb_release() yourself. + */ +bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except expects the stream to start with the message size + * encoded as varint. Corresponds to parseDelimitedFrom() in Google's + * protobuf API. */ -#define PB_DECODE_NOINIT 0x01U -#define PB_DECODE_DELIMITED 0x02U -#define PB_DECODE_NULLTERMINATED 0x04U -bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags); +bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT) -#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED) -#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT) -#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED) +/* Same as pb_decode_delimited, except that it does not initialize the destination structure. + * See pb_decode_noinit + */ +bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); + +/* Same as pb_decode, except allows the message to be terminated with a null byte. + * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour + * is not supported in most other protobuf implementations, so pb_decode_delimited() + * is a better option for compatibility. + */ +bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); #ifdef PB_ENABLE_MALLOC /* Release any allocated pointer fields. If you use dynamic allocation, you should * call this for any successfully decoded message when you are done with it. If * pb_decode() returns with an error, the message is already released. */ -void pb_release(const pb_msgdesc_t *fields, void *dest_struct); +void pb_release(const pb_field_t fields[], void *dest_struct); #endif - /************************************** * Functions for manipulating streams * **************************************/ @@ -132,7 +126,6 @@ pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize); */ bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); - /************************************************ * Helper functions for writing field callbacks * ************************************************/ @@ -144,21 +137,19 @@ bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *ta /* Skip the field payload data, given the wire type. */ bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); -/* Decode an integer in the varint format. This works for enum, int32, +/* Decode an integer in the varint format. This works for bool, enum, int32, * int64, uint32 and uint64 field types. */ #ifndef PB_WITHOUT_64BIT bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); #else #define pb_decode_varint pb_decode_varint32 #endif +// uint64_t val2; -/* Decode an integer in the varint format. This works for enum, int32, +/* Decode an integer in the varint format. This works for bool, enum, int32, * and uint32 field types. */ bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); -/* Decode a bool value in varint format. */ -bool pb_decode_bool(pb_istream_t *stream, bool *dest); - /* Decode an integer in the zig-zagged svarint format. This works for sint32 * and sint64. */ #ifndef PB_WITHOUT_64BIT @@ -177,11 +168,6 @@ bool pb_decode_fixed32(pb_istream_t *stream, void *dest); bool pb_decode_fixed64(pb_istream_t *stream, void *dest); #endif -#ifdef PB_CONVERT_DOUBLE_FLOAT -/* Decode a double value into float variable. */ -bool pb_decode_double_as_float(pb_istream_t *stream, float *dest); -#endif - /* Make a limited-length substream for reading a PB_WT_STRING field. */ bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); diff --git a/src/ui/nanopb/pb_encode.c b/src/ui/nanopb/pb_encode.c index 409fec39..41d3c8ae 100644 --- a/src/ui/nanopb/pb_encode.c +++ b/src/ui/nanopb/pb_encode.c @@ -7,6 +7,12 @@ #include "pb_encode.h" #include "pb_common.h" +#ifdef OS_IO_SEPROXYHAL +#include "os.h" +#else +#define PIC(x) x +#endif + /* Use the GCC warn_unused_result attribute to check that all return values * are propagated correctly. On other compilers and gcc before 3.4.0 just * ignore the annotation. @@ -20,22 +26,23 @@ /************************************** * Declarations internal to this file * **************************************/ +typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; + static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); -static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field); -static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field); -static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field); -static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); +static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); -static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high); -static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field); -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static void *pb_const_cast(const void *p); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); #ifdef PB_WITHOUT_64BIT #define pb_int64_t int32_t @@ -45,6 +52,23 @@ static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb #define pb_uint64_t uint64_t #endif +/* --- Function pointers to field encoders --- + * Order in the array must match pb_action_t LTYPE numbering. + */ +static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { + &pb_enc_varint, + &pb_enc_uvarint, + &pb_enc_svarint, + &pb_enc_fixed32, + &pb_enc_fixed64, + + &pb_enc_bytes, + &pb_enc_string, + &pb_enc_submessage, + NULL, /* extensions */ + &pb_enc_fixed_length_bytes +}; + /******************************* * pb_ostream_t implementation * *******************************/ @@ -80,7 +104,7 @@ pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) { - if (count > 0 && stream->callback != NULL) + if (stream->callback != NULL) { if (stream->bytes_written + count > stream->max_size) PB_RETURN_ERROR(stream, "stream full"); @@ -102,40 +126,20 @@ bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t cou * Encode a single field * *************************/ -/* Read a bool value without causing undefined behavior even if the value - * is invalid. See issue #434 and - * https://stackoverflow.com/questions/27661768/weird-results-for-conditional - */ -static bool safe_read_bool(const void *pSize) -{ - const char *p = (const char *)pSize; - size_t i; - for (i = 0; i < sizeof(bool); i++) - { - if (p[i] != 0) - return true; - } - return false; -} - /* Encode a static array. Handles the size calculations and possible packing. */ -static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *field) +static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, + const void *pData, size_t count, pb_encoder_t func) { - pb_size_t i; - pb_size_t count; -#ifndef PB_ENCODE_ARRAYS_UNPACKED + size_t i; + const void *p; size_t size; -#endif - - count = *(pb_size_t*)field->pSize; - + if (count == 0) return true; if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) PB_RETURN_ERROR(stream, "array max size exceeded"); -#ifndef PB_ENCODE_ARRAYS_UNPACKED /* We always pack arrays if the datatype allows it. */ if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { @@ -145,23 +149,22 @@ static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *fiel /* Determine the total size of packed array. */ if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { - size = 4 * (size_t)count; + size = 4 * count; } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { - size = 8 * (size_t)count; + size = 8 * count; } else { pb_ostream_t sizestream = PB_OSTREAM_SIZING; - void *pData_orig = field->pData; + p = pData; for (i = 0; i < count; i++) { - if (!pb_enc_varint(&sizestream, field)) - PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream)); - field->pData = (char*)field->pData + field->data_size; + if (!func(&sizestream, field, p)) + return false; + p = (const char*)p + field->data_size; } - field->pData = pData_orig; size = sizestream.bytes_written; } @@ -172,27 +175,22 @@ static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *fiel return pb_write(stream, NULL, size); /* Just sizing.. */ /* Write the data */ + p = pData; for (i = 0; i < count; i++) { - if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || PB_LTYPE(field->type) == PB_LTYPE_FIXED64) - { - if (!pb_enc_fixed(stream, field)) - return false; - } - else - { - if (!pb_enc_varint(stream, field)) - return false; - } - - field->pData = (char*)field->pData + field->data_size; + if (!func(stream, field, p)) + return false; + p = (const char*)p + field->data_size; } } - else /* Unpacked fields */ -#endif + else { + p = pData; for (i = 0; i < count; i++) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + /* Normally the data is stored directly in the array entries, but * for pointer-type string and bytes fields, the array entries are * actually pointers themselves also. So we have to dereference once @@ -201,32 +199,15 @@ static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *fiel (PB_LTYPE(field->type) == PB_LTYPE_STRING || PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { - bool status; - void *pData_orig = field->pData; - field->pData = *(void* const*)field->pData; - - if (!field->pData) - { - /* Null pointer in array is treated as empty string / bytes */ - status = pb_encode_tag_for_field(stream, field) && - pb_encode_varint(stream, 0); - } - else - { - status = encode_basic_field(stream, field); - } - - field->pData = pData_orig; - - if (!status) - return false; + if (!func(stream, field, *(const void* const*)p)) + return false; } else { - if (!encode_basic_field(stream, field)) + if (!func(stream, field, p)) return false; } - field->pData = (char*)field->pData + field->data_size; + p = (const char*)p + field->data_size; } } @@ -235,43 +216,44 @@ static bool checkreturn encode_array(pb_ostream_t *stream, pb_field_iter_t *fiel /* In proto3, all fields are optional and are only encoded if their value is "non-zero". * This function implements the check for the zero value. */ -static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *field) +static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) { pb_type_t type = field->type; + const void *pSize = (const char*)pData + field->size_offset; - if (PB_ATYPE(type) == PB_ATYPE_STATIC) + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) { - if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) - { - /* Required proto2 fields inside proto3 submessage, pretty rare case */ - return false; - } - else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) - { - /* Repeated fields inside proto3 submessage: present if count != 0 */ - return *(const pb_size_t*)field->pSize == 0; - } - else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - /* Oneof fields */ - return *(const pb_size_t*)field->pSize == 0; - } - else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) - { - /* Proto2 optional fields inside proto3 message, or proto3 - * submessage fields. */ - return safe_read_bool(field->pSize) == false; - } + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } + else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) + { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) + { + /* Oneof fields */ + return *(const pb_size_t*)pSize == 0; + } + else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) + { + /* Proto2 optional fields inside proto3 submessage */ + return *(const bool*)pSize == false; + } - /* Rest is proto3 singular fields */ + /* Rest is proto3 singular fields */ + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) + { if (PB_LTYPE(type) == PB_LTYPE_BYTES) { - const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData; + const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; return bytes->size == 0; } else if (PB_LTYPE(type) == PB_LTYPE_STRING) { - return *(const char*)field->pData == '\0'; + return *(const char*)pData == '\0'; } else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) { @@ -280,20 +262,19 @@ static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *fie * it anyway. */ return field->data_size == 0; } - else if (PB_LTYPE_IS_SUBMSG(type)) + else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) { /* Check all fields in the submessage to find if any of them * are non-zero. The comparison cannot be done byte-per-byte * because the C struct may contain padding bytes that must - * be skipped. Note that usually proto3 submessages have - * a separate has_field that is checked earlier in this if. + * be skipped. */ pb_field_iter_t iter; - if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData)) + if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) { do { - if (!pb_check_proto3_default_value(&iter)) + if (!pb_check_proto3_default_value(iter.pos, iter.pData)) { return false; } @@ -303,159 +284,175 @@ static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *fie } } - { - /* Catch-all branch that does byte-per-byte comparison for zero value. - * - * This is for all pointer fields, and for static PB_LTYPE_VARINT, - * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also - * callback fields. These all have integer or pointer value which - * can be compared with 0. - */ - pb_size_t i; - const char *p = (const char*)field->pData; - for (i = 0; i < field->data_size; i++) - { - if (p[i] != 0) - { - return false; - } - } - - return true; - } + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char*)pData; + for (i = 0; i < field->data_size; i++) + { + if (p[i] != 0) + { + return false; + } + } + + return true; + } } /* Encode a field with static or pointer allocation, i.e. one whose data * is available to the encoder directly. */ -static bool checkreturn encode_basic_field(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) { - if (!field->pData) + pb_encoder_t func; + bool implicit_has; + const void *pSize = &implicit_has; + + func = PB_ENCODERS[PB_LTYPE(field->type)]; + + if (field->size_offset) { - /* Missing pointer field */ - return true; + /* Static optional, repeated or oneof field */ + pSize = (const char*)pData + field->size_offset; } - - if (!pb_encode_tag_for_field(stream, field)) - return false; - - switch (PB_LTYPE(field->type)) + else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) { - case PB_LTYPE_BOOL: - return pb_enc_bool(stream, field); - - case PB_LTYPE_VARINT: - case PB_LTYPE_UVARINT: - case PB_LTYPE_SVARINT: - return pb_enc_varint(stream, field); - - case PB_LTYPE_FIXED32: - case PB_LTYPE_FIXED64: - return pb_enc_fixed(stream, field); - - case PB_LTYPE_BYTES: - return pb_enc_bytes(stream, field); - - case PB_LTYPE_STRING: - return pb_enc_string(stream, field); + /* Proto3 style field, optional but without explicit has_ field. */ + implicit_has = !pb_check_proto3_default_value(field, pData); + } + else + { + /* Required field, always present */ + implicit_has = true; + } - case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_SUBMSG_W_CB: - return pb_enc_submessage(stream, field); + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) + { + /* pData is a pointer to the field, which contains pointer to + * the data. If the 2nd pointer is NULL, it is interpreted as if + * the has_field was false. + */ + pData = *(const void* const*)pData; + implicit_has = (pData != NULL); + } - case PB_LTYPE_FIXED_LENGTH_BYTES: - return pb_enc_fixed_length_bytes(stream, field); + switch (PB_HTYPE(field->type)) + { + case PB_HTYPE_REQUIRED: + if (!pData) + PB_RETURN_ERROR(stream, "missing required field"); + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!((pb_encoder_t)PIC(func))(stream, field, pData)) + return false; + break; + + case PB_HTYPE_OPTIONAL: + if (*(const bool*)pSize) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!((pb_encoder_t)PIC(func))(stream, field, pData)) + return false; + } + break; + + case PB_HTYPE_REPEATED: + if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func)) + return false; + break; + + case PB_HTYPE_ONEOF: + if (*(const pb_size_t*)pSize == field->tag) + { + if (!pb_encode_tag_for_field(stream, field)) + return false; + if (!((pb_encoder_t)PIC(func))(stream, field, pData)) + return false; + } + break; + default: PB_RETURN_ERROR(stream, "invalid field type"); } + return true; } /* Encode a field with callback semantics. This means that a user function is * called to provide and encode the actual data. */ -static bool checkreturn encode_callback_field(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) { - if (field->descriptor->field_callback != NULL) + const pb_callback_t *callback = (const pb_callback_t*)pData; + +#ifdef PB_OLD_CALLBACK_STYLE + const void *arg = callback->arg; +#else + void * const *arg = &(callback->arg); +#endif + + if (callback->funcs.encode != NULL) { - if (!field->descriptor->field_callback(NULL, stream, field)) + if (!callback->funcs.encode(stream, field, arg)) PB_RETURN_ERROR(stream, "callback error"); } return true; } -/* Encode a single field of any callback, pointer or static type. */ -static bool checkreturn encode_field(pb_ostream_t *stream, pb_field_iter_t *field) +/* Encode a single field of any callback or static type. */ +static bool checkreturn encode_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) { - /* Check field presence */ - if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) + switch (PB_ATYPE(field->type)) { - if (*(const pb_size_t*)field->pSize != field->tag) - { - /* Different type oneof field */ - return true; - } - } - else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) - { - if (field->pSize) - { - if (safe_read_bool(field->pSize) == false) - { - /* Missing optional field */ - return true; - } - } - else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) - { - /* Proto3 singular field */ - if (pb_check_proto3_default_value(field)) - return true; - } - } - - if (!field->pData) - { - if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED) - PB_RETURN_ERROR(stream, "missing required field"); - - /* Pointer field set to NULL */ - return true; + case PB_ATYPE_STATIC: + case PB_ATYPE_POINTER: + return encode_basic_field(stream, field, pData); + + case PB_ATYPE_CALLBACK: + return encode_callback_field(stream, field, pData); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); } +} - /* Then encode field contents */ - if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK) - { - return encode_callback_field(stream, field); - } - else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) +/* Default handler for extension fields. Expects to have a pb_field_t + * pointer in the extension->type->arg field. */ +static bool checkreturn default_extension_encoder(pb_ostream_t *stream, + const pb_extension_t *extension) +{ + const pb_field_t *field = (const pb_field_t*)extension->type->arg; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { - return encode_array(stream, field); + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + return encode_field(stream, field, &extension->dest); } else { - return encode_basic_field(stream, field); + return encode_field(stream, field, extension->dest); } } -/* Default handler for extension fields. Expects to have a pb_msgdesc_t - * pointer in the extension->type->arg field, pointing to a message with - * only one field in it. */ -static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension) -{ - pb_field_iter_t iter; - - if (!pb_field_iter_begin_extension_const(&iter, extension)) - PB_RETURN_ERROR(stream, "invalid extension"); - - return encode_field(stream, &iter); -} - - /* Walk through all the registered extensions and give them a chance * to encode themselves. */ -static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_t *field, const void *pData) { - const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData; - + const pb_extension_t *extension = *(const pb_extension_t* const *)pData; + PB_UNUSED(field); + while (extension) { bool status; @@ -477,23 +474,35 @@ static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_fi * Encode all fields * *********************/ -bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +static void *pb_const_cast(const void *p) +{ + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { pb_field_iter_t iter; - if (!pb_field_iter_begin_const(&iter, fields, src_struct)) - return true; /* Empty message type */ - + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + do { - if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) + if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) { /* Special case for the extension field placeholder */ - if (!encode_extension_field(stream, &iter)) + if (!encode_extension_field(stream, iter.pos, iter.pData)) return false; } else { /* Regular field */ - if (!encode_field(stream, &iter)) + if (!encode_field(stream, iter.pos, iter.pData)) return false; } } while (pb_field_iter_next(&iter)); @@ -501,28 +510,22 @@ bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, con return true; } -bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags) +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { - if ((flags & PB_ENCODE_DELIMITED) != 0) - { return pb_encode_submessage(stream, fields, src_struct); - } - else if ((flags & PB_ENCODE_NULLTERMINATED) != 0) - { +} + +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) +{ const pb_byte_t zero = 0; if (!pb_encode(stream, fields, src_struct)) return false; return pb_write(stream, &zero, 1); - } - else - { - return pb_encode(stream, fields, src_struct); - } } -bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct) +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) { pb_ostream_t stream = PB_OSTREAM_SIZING; @@ -536,60 +539,28 @@ bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *s /******************** * Helper functions * ********************/ - -/* This function avoids 64-bit shifts as they are quite slow on many platforms. */ -static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, uint32_t high) +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) { - size_t i = 0; pb_byte_t buffer[10]; - pb_byte_t byte = (pb_byte_t)(low & 0x7F); - low >>= 7; - - while (i < 4 && (low != 0 || high != 0)) + size_t i = 0; + + if (value <= 0x7F) { - byte |= 0x80; - buffer[i++] = byte; - byte = (pb_byte_t)(low & 0x7F); - low >>= 7; + pb_byte_t v = (pb_byte_t)value; + return pb_write(stream, &v, 1); } - if (high) + + while (value) { - byte = (pb_byte_t)(byte | ((high & 0x07) << 4)); - high >>= 3; - - while (high) - { - byte |= 0x80; - buffer[i++] = byte; - byte = (pb_byte_t)(high & 0x7F); - high >>= 7; - } + buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); + value >>= 7; + i++; } - - buffer[i++] = byte; - + buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ return pb_write(stream, buffer, i); } -bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) -{ - if (value <= 0x7F) - { - /* Fast path: single byte */ - pb_byte_t byte = (pb_byte_t)value; - return pb_write(stream, &byte, 1); - } - else - { -#ifdef PB_WITHOUT_64BIT - return pb_encode_varint_32(stream, value, 0); -#else - return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)(value >> 32)); -#endif - } -} - bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) { pb_uint64_t zigzagged; @@ -635,12 +606,11 @@ bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, ui return pb_encode_varint(stream, tag); } -bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* field ) +bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) { pb_wire_type_t wiretype; switch (PB_LTYPE(field->type)) { - case PB_LTYPE_BOOL: case PB_LTYPE_VARINT: case PB_LTYPE_UVARINT: case PB_LTYPE_SVARINT: @@ -658,7 +628,6 @@ bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* fiel case PB_LTYPE_BYTES: case PB_LTYPE_STRING: case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_SUBMSG_W_CB: case PB_LTYPE_FIXED_LENGTH_BYTES: wiretype = PB_WT_STRING; break; @@ -666,7 +635,6 @@ bool pb_encode_tag_for_field ( pb_ostream_t* stream, const pb_field_iter_t* fiel default: PB_RETURN_ERROR(stream, "invalid field type"); } - return pb_encode_tag(stream, wiretype, field->tag); } @@ -678,7 +646,7 @@ bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, return pb_write(stream, buffer, size); } -bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct) +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) { /* First calculate the message size using a non-writing substream. */ pb_ostream_t substream = PB_OSTREAM_SIZING; @@ -730,93 +698,84 @@ bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t * /* Field encoders */ -static bool checkreturn pb_enc_bool(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - uint32_t value = safe_read_bool(field->pData) ? 1 : 0; - PB_UNUSED(field); - return pb_encode_varint(stream, value); + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, (pb_uint64_t)value); } -static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) - { - /* Perform unsigned integer extension */ - pb_uint64_t value = 0; - - if (field->data_size == sizeof(uint_least8_t)) - value = *(const uint_least8_t*)field->pData; - else if (field->data_size == sizeof(uint_least16_t)) - value = *(const uint_least16_t*)field->pData; - else if (field->data_size == sizeof(uint32_t)) - value = *(const uint32_t*)field->pData; - else if (field->data_size == sizeof(pb_uint64_t)) - value = *(const pb_uint64_t*)field->pData; - else - PB_RETURN_ERROR(stream, "invalid data_size"); - - return pb_encode_varint(stream, value); - } + pb_uint64_t value = 0; + + if (field->data_size == sizeof(uint_least8_t)) + value = *(const uint_least8_t*)src; + else if (field->data_size == sizeof(uint_least16_t)) + value = *(const uint_least16_t*)src; + else if (field->data_size == sizeof(uint32_t)) + value = *(const uint32_t*)src; + else if (field->data_size == sizeof(pb_uint64_t)) + value = *(const pb_uint64_t*)src; else - { - /* Perform signed integer extension */ - pb_int64_t value = 0; - - if (field->data_size == sizeof(int_least8_t)) - value = *(const int_least8_t*)field->pData; - else if (field->data_size == sizeof(int_least16_t)) - value = *(const int_least16_t*)field->pData; - else if (field->data_size == sizeof(int32_t)) - value = *(const int32_t*)field->pData; - else if (field->data_size == sizeof(pb_int64_t)) - value = *(const pb_int64_t*)field->pData; - else - PB_RETURN_ERROR(stream, "invalid data_size"); - - if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) - return pb_encode_svarint(stream, value); -#ifdef PB_WITHOUT_64BIT - else if (value < 0) - return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1); -#endif - else - return pb_encode_varint(stream, (pb_uint64_t)value); - - } + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_varint(stream, value); } -static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) { -#ifdef PB_CONVERT_DOUBLE_FLOAT - if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64) - { - return pb_encode_float_as_double(stream, *(float*)field->pData); - } -#endif + pb_int64_t value = 0; + + if (field->data_size == sizeof(int_least8_t)) + value = *(const int_least8_t*)src; + else if (field->data_size == sizeof(int_least16_t)) + value = *(const int_least16_t*)src; + else if (field->data_size == sizeof(int32_t)) + value = *(const int32_t*)src; + else if (field->data_size == sizeof(pb_int64_t)) + value = *(const pb_int64_t*)src; + else + PB_RETURN_ERROR(stream, "invalid data_size"); + + return pb_encode_svarint(stream, value); +} - if (field->data_size == sizeof(uint32_t)) - { - return pb_encode_fixed32(stream, field->pData); - } +static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); #ifndef PB_WITHOUT_64BIT - else if (field->data_size == sizeof(uint64_t)) - { - return pb_encode_fixed64(stream, field->pData); - } + return pb_encode_fixed64(stream, src); +#else + PB_UNUSED(src); + PB_RETURN_ERROR(stream, "no 64bit support"); #endif - else - { - PB_RETURN_ERROR(stream, "invalid data_size"); - } } -static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) +{ + PB_UNUSED(field); + return pb_encode_fixed32(stream, src); +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) { const pb_bytes_array_t *bytes = NULL; - bytes = (const pb_bytes_array_t*)field->pData; + bytes = (const pb_bytes_array_t*)src; - if (bytes == NULL) + if (src == NULL) { /* Treat null pointer as an empty bytes field */ return pb_encode_string(stream, NULL, 0); @@ -828,131 +787,45 @@ static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t PB_RETURN_ERROR(stream, "bytes size exceeded"); } - return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size); + return pb_encode_string(stream, bytes->bytes, bytes->size); } -static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) { size_t size = 0; - size_t max_size = (size_t)field->data_size; - const char *str = (const char*)field->pData; + size_t max_size = field->data_size; + const char *p = (const char*)src; if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { max_size = (size_t)-1; - } - else - { - /* pb_dec_string() assumes string fields end with a null - * terminator when the type isn't PB_ATYPE_POINTER, so we - * shouldn't allow more than max-1 bytes to be written to - * allow space for the null terminator. - */ - if (max_size == 0) - PB_RETURN_ERROR(stream, "zero-length string"); - max_size -= 1; - } - - - if (str == NULL) + if (src == NULL) { size = 0; /* Treat null pointer as an empty string */ } else { - const char *p = str; - /* strnlen() is not always available, so just use a loop */ while (size < max_size && *p != '\0') { size++; p++; } - - if (*p != '\0') - { - PB_RETURN_ERROR(stream, "unterminated string"); - } } -#ifdef PB_VALIDATE_UTF8 - if (!pb_validate_utf8(str)) - PB_RETURN_ERROR(stream, "invalid utf8"); -#endif - - return pb_encode_string(stream, (const pb_byte_t*)str, size); + return pb_encode_string(stream, (const pb_byte_t*)src, size); } -static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - if (field->submsg_desc == NULL) + if (field->ptr == NULL) PB_RETURN_ERROR(stream, "invalid field descriptor"); - - if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) - { - /* Message callback is stored right before pSize. */ - pb_callback_t *callback = (pb_callback_t*)field->pSize - 1; - if (callback->funcs.encode) - { - if (!callback->funcs.encode(stream, field, &callback->arg)) - return false; - } - } - return pb_encode_submessage(stream, field->submsg_desc, field->pData); + return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); } -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) { - return pb_encode_string(stream, (const pb_byte_t*)field->pData, (size_t)field->data_size); + return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); } -#ifdef PB_CONVERT_DOUBLE_FLOAT -bool pb_encode_float_as_double(pb_ostream_t *stream, float value) -{ - union { float f; uint32_t i; } in; - uint_least8_t sign; - int exponent; - uint64_t mantissa; - - in.f = value; - - /* Decompose input value */ - sign = (uint_least8_t)((in.i >> 31) & 1); - exponent = (int)((in.i >> 23) & 0xFF) - 127; - mantissa = in.i & 0x7FFFFF; - - if (exponent == 128) - { - /* Special value (NaN etc.) */ - exponent = 1024; - } - else if (exponent == -127) - { - if (!mantissa) - { - /* Zero */ - exponent = -1023; - } - else - { - /* Denormalized */ - mantissa <<= 1; - while (!(mantissa & 0x800000)) - { - mantissa <<= 1; - exponent--; - } - mantissa &= 0x7FFFFF; - } - } - - /* Combine fields */ - mantissa <<= 29; - mantissa |= (uint64_t)(exponent + 1023) << 52; - mantissa |= (uint64_t)sign << 63; - - return pb_encode_fixed64(stream, &mantissa); -} -#endif diff --git a/src/ui/nanopb/pb_encode.h b/src/ui/nanopb/pb_encode.h index 88e246a2..8bf78dd5 100644 --- a/src/ui/nanopb/pb_encode.h +++ b/src/ui/nanopb/pb_encode.h @@ -64,31 +64,22 @@ struct pb_ostream_s * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); * pb_encode(&stream, MyMessage_fields, &msg); */ -bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); +bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); -/* Extended version of pb_encode, with several options to control the - * encoding process: - * - * PB_ENCODE_DELIMITED: Prepend the length of message as a varint. - * Corresponds to writeDelimitedTo() in Google's - * protobuf API. - * - * PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination. - * NOTE: This behaviour is not supported in most other - * protobuf implementations, so PB_ENCODE_DELIMITED - * is a better option for compatibility. +/* Same as pb_encode, but prepends the length of the message as a varint. + * Corresponds to writeDelimitedTo() in Google's protobuf API. */ -#define PB_ENCODE_DELIMITED 0x02U -#define PB_ENCODE_NULLTERMINATED 0x04U -bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags); +bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED) -#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED) +/* Same as pb_encode, but appends a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() + * is a better option for compatibility. + */ +bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); /* Encode the message to get the size of the encoded data, but do not store * the data. */ -bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct); +bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); /************************************** * Functions for manipulating streams * @@ -130,7 +121,7 @@ bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); /* Encode field header based on type and field number defined in the field * structure. Call this from the callback before writing out field contents. */ -bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field); +bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); /* Encode field header by manually specifing wire type. You need to use this * if you want to write out packed arrays from a callback field. */ @@ -165,18 +156,12 @@ bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); #endif -#ifdef PB_CONVERT_DOUBLE_FLOAT -/* Encode a float value so that it appears like a double in the encoded - * message. */ -bool pb_encode_float_as_double(pb_ostream_t *stream, float value); -#endif - /* Encode a submessage field. * You need to pass the pb_field_t array and pointer to struct, just like * with pb_encode(). This internally encodes the submessage twice, first to * calculate message size and then to actually write it out. */ -bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct); +bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/ui/nanopb/simple.pb.c b/src/ui/nanopb/simple.pb.c index a487f136..b92dc4c7 100644 --- a/src/ui/nanopb/simple.pb.c +++ b/src/ui/nanopb/simple.pb.c @@ -1,12 +1,19 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.2-dev */ +/* Generated by nanopb-0.3.9.3 at Tue Apr 7 15:35:57 2020. */ #include "simple.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(SimpleMessage, SimpleMessage, AUTO) +const pb_field_t SimpleMessage_fields[2] = { + PB_FIELD( 1, INT32 , REQUIRED, STATIC , FIRST, SimpleMessage, lucky_number, lucky_number, 0), + PB_LAST_FIELD +}; + +/* @@protoc_insertion_point(eof) */ diff --git a/src/ui/nanopb/simple.pb.h b/src/ui/nanopb/simple.pb.h index 4b8d5671..e94e8ceb 100644 --- a/src/ui/nanopb/simple.pb.h +++ b/src/ui/nanopb/simple.pb.h @@ -1,11 +1,12 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.2-dev */ +/* Generated by nanopb-0.3.9.3 at Tue Apr 7 15:35:57 2020. */ #ifndef PB_SIMPLE_PB_H_INCLUDED #define PB_SIMPLE_PB_H_INCLUDED #include -#if PB_PROTO_HEADER_VERSION != 40 +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif @@ -16,8 +17,10 @@ extern "C" { /* Struct definitions */ typedef struct _SimpleMessage { int32_t lucky_number; +/* @@protoc_insertion_point(struct:SimpleMessage) */ } SimpleMessage; +/* Default values for struct fields */ /* Initializer values for message structs */ #define SimpleMessage_init_default {0} @@ -27,21 +30,22 @@ typedef struct _SimpleMessage { #define SimpleMessage_lucky_number_tag 1 /* Struct field encoding specification for nanopb */ -#define SimpleMessage_FIELDLIST(X, a) \ -X(a, STATIC, REQUIRED, INT32, lucky_number, 1) -#define SimpleMessage_CALLBACK NULL -#define SimpleMessage_DEFAULT NULL - -extern const pb_msgdesc_t SimpleMessage_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define SimpleMessage_fields &SimpleMessage_msg +extern const pb_field_t SimpleMessage_fields[2]; /* Maximum encoded size of messages (where known) */ #define SimpleMessage_size 11 +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define SIMPLE_MESSAGES \ + + +#endif + #ifdef __cplusplus } /* extern "C" */ #endif +/* @@protoc_insertion_point(eof) */ #endif diff --git a/src/ui/ui.c b/src/ui/ui.c index 46a428af..de9fdb6a 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -185,7 +185,7 @@ void make_allowed_ui_steps(bool is_last) { bool status; /* Encode our message */ - //{ + { /* Allocate space on the stack to store the message data. * * Nanopb generates simple struct definitions for all the messages. @@ -207,7 +207,7 @@ void make_allowed_ui_steps(bool is_last) { PRINTF("Encoding failed: %s\n", PB_GET_ERROR(&stream)); return; } - //} + } /* Now we could transmit the message over network, store it in a file or * wrap it to a pigeon's leg. @@ -215,28 +215,27 @@ void make_allowed_ui_steps(bool is_last) { /* But because we are lazy, we will just decode it immediately. */ - //{ - // PRINTF("init message\n"); + { + PRINTF("init message\n"); /* Allocate space for the decoded message. */ - // SimpleMessage message = SimpleMessage_init_zero; - // PRINTF("create stream\n"); + SimpleMessage message = SimpleMessage_init_zero; + PRINTF("create stream\n"); /* Create a stream that reads from the buffer. */ - // pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); - // PRINTF("decode message\n"); + pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); + PRINTF("decode message\n"); /* Now we are ready to decode the message. */ - // status = pb_decode(&stream, SimpleMessage_fields, &message); + status = pb_decode(&stream, SimpleMessage_fields, &message); /* Check for errors... */ - // if (!status) - //{ - // PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); - // return ; - //} + if (!status) + { + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + return ; + } /* Print the data contained in the message. */ - // PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); - //} - //*****END TESTING SIMPLE***** + PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); + } } // Show the transaction details for the user to approve From 343c857e2e43a1827ea5cae713eca9dd45d2a34d Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Tue, 21 Apr 2020 11:48:36 +0400 Subject: [PATCH 05/26] add waves protobuf files, try to decode message --- Makefile | 2 + python/amount_pb2.py | 76 + python/ledger-waves.py | 101 +- python/order_pb2.py | 221 +++ python/recipient_pb2.py | 85 + python/transaction_pb2.py | 1373 +++++++++++++++++ src/main.c | 66 +- src/main.h | 1 + src/{ui => }/nanopb/pb.h | 0 src/{ui => }/nanopb/pb_common.c | 0 src/{ui => }/nanopb/pb_common.h | 0 src/nanopb/pb_custom.c | 155 ++ src/nanopb/pb_custom.h | 31 + src/{ui => }/nanopb/pb_decode.c | 0 src/{ui => }/nanopb/pb_decode.h | 0 src/{ui => }/nanopb/pb_encode.c | 0 src/{ui => }/nanopb/pb_encode.h | 0 src/nanopb_stubs/amount.pb.c | 20 + .../simple.pb.h => nanopb_stubs/amount.pb.h} | 28 +- src/nanopb_stubs/order.pb.c | 61 + src/nanopb_stubs/order.pb.h | 96 ++ src/nanopb_stubs/recipient.pb.c | 20 + src/nanopb_stubs/recipient.pb.h | 57 + src/nanopb_stubs/transaction.pb.c | 193 +++ src/nanopb_stubs/transaction.pb.h | 382 +++++ src/ui/nanopb/simple.pb.c | 19 - src/ui/nanopb/simple.proto | 9 - src/ui/ui.c | 62 - 28 files changed, 2947 insertions(+), 111 deletions(-) create mode 100644 python/amount_pb2.py create mode 100644 python/order_pb2.py create mode 100644 python/recipient_pb2.py create mode 100644 python/transaction_pb2.py rename src/{ui => }/nanopb/pb.h (100%) rename src/{ui => }/nanopb/pb_common.c (100%) rename src/{ui => }/nanopb/pb_common.h (100%) create mode 100644 src/nanopb/pb_custom.c create mode 100644 src/nanopb/pb_custom.h rename src/{ui => }/nanopb/pb_decode.c (100%) rename src/{ui => }/nanopb/pb_decode.h (100%) rename src/{ui => }/nanopb/pb_encode.c (100%) rename src/{ui => }/nanopb/pb_encode.h (100%) create mode 100644 src/nanopb_stubs/amount.pb.c rename src/{ui/nanopb/simple.pb.h => nanopb_stubs/amount.pb.h} (51%) create mode 100644 src/nanopb_stubs/order.pb.c create mode 100644 src/nanopb_stubs/order.pb.h create mode 100644 src/nanopb_stubs/recipient.pb.c create mode 100644 src/nanopb_stubs/recipient.pb.h create mode 100644 src/nanopb_stubs/transaction.pb.c create mode 100644 src/nanopb_stubs/transaction.pb.h delete mode 100644 src/ui/nanopb/simple.pb.c delete mode 100644 src/ui/nanopb/simple.proto diff --git a/Makefile b/Makefile index 462224d8..996675c4 100755 --- a/Makefile +++ b/Makefile @@ -103,8 +103,10 @@ ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf + DEFINES += HAVE_PRINTF_PB PRINTF_PB=mcu_usb_printf else DEFINES += HAVE_PRINTF PRINTF=screen_printf + DEFINES += HAVE_PRINTF_PB PRINTF_PB=screen_printf endif else DEFINES += PRINTF\(...\)= diff --git a/python/amount_pb2.py b/python/amount_pb2.py new file mode 100644 index 00000000..c5c56e7d --- /dev/null +++ b/python/amount_pb2.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: amount.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='amount.proto', + package='waves', + syntax='proto3', + serialized_options=b'\n\032com.wavesplatform.protobuf\252\002\005Waves', + serialized_pb=b'\n\x0c\x61mount.proto\x12\x05waves\"*\n\x06\x41mount\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\x42$\n\x1a\x63om.wavesplatform.protobuf\xaa\x02\x05Wavesb\x06proto3' +) + + + + +_AMOUNT = _descriptor.Descriptor( + name='Amount', + full_name='waves.Amount', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_id', full_name='waves.Amount.asset_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.Amount.amount', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=23, + serialized_end=65, +) + +DESCRIPTOR.message_types_by_name['Amount'] = _AMOUNT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Amount = _reflection.GeneratedProtocolMessageType('Amount', (_message.Message,), { + 'DESCRIPTOR' : _AMOUNT, + '__module__' : 'amount_pb2' + # @@protoc_insertion_point(class_scope:waves.Amount) + }) +_sym_db.RegisterMessage(Amount) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index e403e916..96cb5de8 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -23,6 +23,10 @@ import pywaves.crypto as pwcrypto import pywaves as pw import time +import binascii +from amount_pb2 import Amount +from transaction_pb2 import Transaction, TransferTransactionData, Attachment +from recipient_pb2 import Recipient global dongle dongle = None @@ -228,6 +232,17 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee return sData +def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 2): + if timestamp == 0: + timestamp = int(time.time() * 1000) + msg = Attachment(string_value = attachment) + to = Recipient(public_key_hash=base58.b58decode(recipient.address)) + amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + transfer = TransferTransactionData(recipient=to, amount=amountTx, attachment=msg) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b''), amount=txFee) + trx = Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) + return trx.SerializeToString() + while (True): while (dongle == None): try: @@ -244,7 +259,8 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee print(colors.fg.white + "\t 1. Get PublicKey/Address from Ledger Nano S" + colors.reset) print(colors.fg.white + "\t 2. Sign tx using Ledger Nano S" + colors.reset) print(colors.fg.white + "\t 3. Get app version from Ledger Nano S" + colors.reset) - print(colors.fg.white + "\t 4. Exit" + colors.reset) + print(colors.fg.white + "\t 4. Sign protobuf tx using Ledger Nano S" + colors.reset) + print(colors.fg.white + "\t 5. Exit" + colors.reset) select = raw_input(colors.fg.cyan + "Please select> " + colors.reset) if (select == "1"): @@ -289,6 +305,7 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: # 2 first bytes aren't the tx data, but info type for the ledger + print(len(some_transfer_bytes)) binary_data += b'\4\2' binary_data += struct.pack(">I", len(some_transfer_bytes)) binary_data += some_transfer_bytes @@ -341,5 +358,87 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee elif (select == "3"): version = getVersionFromDongle() print('App version is {}.{}.{}'.format(version[0],version[1],version[2])) + elif (select == "4"): + path = raw_input( + colors.fg.lightblue + "Please input BIP-32 path (for example \"44'/5741564'/0'/0'/1'\")> " + colors.reset) + if len(path) == 0: + path = "44'/5741564'/0'/0'/1'" + binary_data = path_to_bytes(expand_path(path)) + print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) + + # tx amount asset decimals + binary_data += chr(8) + # fee amount asset decimals + binary_data += chr(8) + + # Tx info + # + # amount: 1 + # asset: 9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t + # from: 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # to: 3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK + # attachment: privet + # fee: 0.001 + # fee asset: WAVES + some_transfer_bytes = build_transfer_protobuf('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, + 'privet', timestamp = 1526477921829) + #some_transfer_bytes = b"0aa40108571220b985d724da1564a6354040b1718b8c8e8c59533a20b71ba3c64d5dfe7f379f381a270a200080800142003a8024017fef3519e54affbcae5c01347f648064019b0081c92c10d2b9ea0a20f398cdf7b3ca8fd03e2802c206480a160a1496639366f56efd312248d1edf056070fd5b8941c122a0a204a83e780ff016100147f073b2580ff80ffb9eba30087f400cdb2dc3b5d017c4e1099eebaf4c6b2121a021a00121100d716230100d88280edcdc30ce97f64ed122001807701fd7f01d37fb87f88ffbe01c0ff01ff010005afffcb7fb201a0f4b974122c8c8000ff0a7fff8015381f807801c1007f7f01d700c521ff018dc700017f80807680097f39378e01b500804f122980099e8b80ffff00ad2500870080017f7f880b2ca72e7fff175a00f0da00ff00803dbd2bff8000995c" + + input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( + str(some_transfer_bytes)) + "\")> " + colors.reset) + if len(input) == 0: + # 2 first bytes aren't the tx data, but info type for the ledger + binary_data += b'\4\2' + binary_data += struct.pack(">I", len(some_transfer_bytes)) + binary_data += some_transfer_bytes + binary_data += some_transfer_bytes + print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) + else: + binary_input = base58.b58decode(input) + binary_data += struct.pack(">I", len(binary_input)) + binary_data += binary_input + binary_data += binary_input + print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) + print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) + signature = None + while (True): + try: + offset = 0 + while offset != len(binary_data): + if (len(binary_data) - offset) > CHUNK_SIZE: + chunk = binary_data[offset: offset + CHUNK_SIZE] + else: + chunk = binary_data[offset:] + if (offset + len(chunk)) == len(binary_data): + p1 = 0x80 + else: + p1 = 0x00 + + if (offset == 0): + print("Waiting for approval to sign on the Ledger Nano S") + + apdu = bytes("8002".decode('hex')) + chr(p1) + chain_id + chr(len(chunk)) + bytes(chunk) + signature = dongle.exchange(apdu) + offset += len(chunk) + + print("signature " + base58.b58encode(str(signature))) + break + except CommException as e: + if (e.sw == 0x6990): + print(colors.fg.red + "Transaction buffer max size reached." + colors.reset) + if (e.sw == 0x6985): + print(colors.fg.red + "Required condition failed." + colors.reset) + if (e.sw == 0x9100): + print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + break + except Exception as e: + print(e, type(e)) + answer = raw_input( + "Please connect your Ledger Nano S, unlock, and launch the Waves app. Press when ready. (Q quits)") + if (answer.upper() == 'Q'): + sys.exit(0) + sys.exc_clear() else: break diff --git a/python/order_pb2.py b/python/order_pb2.py new file mode 100644 index 00000000..2feffdd0 --- /dev/null +++ b/python/order_pb2.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: order.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import amount_pb2 as amount__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='order.proto', + package='waves', + syntax='proto3', + serialized_options=b'\n com.wavesplatform.protobuf.order\252\002\005Waves', + serialized_pb=b'\n\x0border.proto\x12\x05waves\x1a\x0c\x61mount.proto\"<\n\tAssetPair\x12\x17\n\x0f\x61mount_asset_id\x18\x01 \x01(\x0c\x12\x16\n\x0eprice_asset_id\x18\x02 \x01(\x0c\"\xc3\x02\n\x05Order\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x12matcher_public_key\x18\x03 \x01(\x0c\x12$\n\nasset_pair\x18\x04 \x01(\x0b\x32\x10.waves.AssetPair\x12%\n\norder_side\x18\x05 \x01(\x0e\x32\x11.waves.Order.Side\x12\x0e\n\x06\x61mount\x18\x06 \x01(\x03\x12\r\n\x05price\x18\x07 \x01(\x03\x12\x11\n\ttimestamp\x18\x08 \x01(\x03\x12\x12\n\nexpiration\x18\t \x01(\x03\x12\"\n\x0bmatcher_fee\x18\n \x01(\x0b\x32\r.waves.Amount\x12\x0f\n\x07version\x18\x0b \x01(\x05\x12\x0e\n\x06proofs\x18\x0c \x03(\x0c\"\x19\n\x04Side\x12\x07\n\x03\x42UY\x10\x00\x12\x08\n\x04SELL\x10\x01\x42*\n com.wavesplatform.protobuf.order\xaa\x02\x05Wavesb\x06proto3' + , + dependencies=[amount__pb2.DESCRIPTOR,]) + + + +_ORDER_SIDE = _descriptor.EnumDescriptor( + name='Side', + full_name='waves.Order.Side', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='BUY', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='SELL', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=397, + serialized_end=422, +) +_sym_db.RegisterEnumDescriptor(_ORDER_SIDE) + + +_ASSETPAIR = _descriptor.Descriptor( + name='AssetPair', + full_name='waves.AssetPair', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='amount_asset_id', full_name='waves.AssetPair.amount_asset_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='price_asset_id', full_name='waves.AssetPair.price_asset_id', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=36, + serialized_end=96, +) + + +_ORDER = _descriptor.Descriptor( + name='Order', + full_name='waves.Order', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='chain_id', full_name='waves.Order.chain_id', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sender_public_key', full_name='waves.Order.sender_public_key', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='matcher_public_key', full_name='waves.Order.matcher_public_key', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='asset_pair', full_name='waves.Order.asset_pair', index=3, + number=4, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='order_side', full_name='waves.Order.order_side', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.Order.amount', index=5, + number=6, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='price', full_name='waves.Order.price', index=6, + number=7, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='waves.Order.timestamp', index=7, + number=8, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='expiration', full_name='waves.Order.expiration', index=8, + number=9, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='matcher_fee', full_name='waves.Order.matcher_fee', index=9, + number=10, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='waves.Order.version', index=10, + number=11, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proofs', full_name='waves.Order.proofs', index=11, + number=12, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _ORDER_SIDE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=99, + serialized_end=422, +) + +_ORDER.fields_by_name['asset_pair'].message_type = _ASSETPAIR +_ORDER.fields_by_name['order_side'].enum_type = _ORDER_SIDE +_ORDER.fields_by_name['matcher_fee'].message_type = amount__pb2._AMOUNT +_ORDER_SIDE.containing_type = _ORDER +DESCRIPTOR.message_types_by_name['AssetPair'] = _ASSETPAIR +DESCRIPTOR.message_types_by_name['Order'] = _ORDER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +AssetPair = _reflection.GeneratedProtocolMessageType('AssetPair', (_message.Message,), { + 'DESCRIPTOR' : _ASSETPAIR, + '__module__' : 'order_pb2' + # @@protoc_insertion_point(class_scope:waves.AssetPair) + }) +_sym_db.RegisterMessage(AssetPair) + +Order = _reflection.GeneratedProtocolMessageType('Order', (_message.Message,), { + 'DESCRIPTOR' : _ORDER, + '__module__' : 'order_pb2' + # @@protoc_insertion_point(class_scope:waves.Order) + }) +_sym_db.RegisterMessage(Order) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/python/recipient_pb2.py b/python/recipient_pb2.py new file mode 100644 index 00000000..3bea0040 --- /dev/null +++ b/python/recipient_pb2.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: recipient.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='recipient.proto', + package='waves', + syntax='proto3', + serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', + serialized_pb=b'\n\x0frecipient.proto\x12\x05waves\"D\n\tRecipient\x12\x19\n\x0fpublic_key_hash\x18\x01 \x01(\x0cH\x00\x12\x0f\n\x05\x61lias\x18\x02 \x01(\tH\x00\x42\x0b\n\trecipientB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' +) + + + + +_RECIPIENT = _descriptor.Descriptor( + name='Recipient', + full_name='waves.Recipient', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='public_key_hash', full_name='waves.Recipient.public_key_hash', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='alias', full_name='waves.Recipient.alias', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='recipient', full_name='waves.Recipient.recipient', + index=0, containing_type=None, fields=[]), + ], + serialized_start=26, + serialized_end=94, +) + +_RECIPIENT.oneofs_by_name['recipient'].fields.append( + _RECIPIENT.fields_by_name['public_key_hash']) +_RECIPIENT.fields_by_name['public_key_hash'].containing_oneof = _RECIPIENT.oneofs_by_name['recipient'] +_RECIPIENT.oneofs_by_name['recipient'].fields.append( + _RECIPIENT.fields_by_name['alias']) +_RECIPIENT.fields_by_name['alias'].containing_oneof = _RECIPIENT.oneofs_by_name['recipient'] +DESCRIPTOR.message_types_by_name['Recipient'] = _RECIPIENT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Recipient = _reflection.GeneratedProtocolMessageType('Recipient', (_message.Message,), { + 'DESCRIPTOR' : _RECIPIENT, + '__module__' : 'recipient_pb2' + # @@protoc_insertion_point(class_scope:waves.Recipient) + }) +_sym_db.RegisterMessage(Recipient) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/python/transaction_pb2.py b/python/transaction_pb2.py new file mode 100644 index 00000000..8a2cec8c --- /dev/null +++ b/python/transaction_pb2.py @@ -0,0 +1,1373 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: transaction.proto + +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import amount_pb2 as amount__pb2 +import recipient_pb2 as recipient__pb2 +import order_pb2 as order__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='transaction.proto', + package='waves', + syntax='proto3', + serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', + serialized_pb=b'\n\x11transaction.proto\x12\x05waves\x1a\x0c\x61mount.proto\x1a\x0frecipient.proto\x1a\x0border.proto\"L\n\x11SignedTransaction\x12\'\n\x0btransaction\x18\x01 \x01(\x0b\x32\x12.waves.Transaction\x12\x0e\n\x06proofs\x18\x02 \x03(\x0c\"\xa6\x08\n\x0bTransaction\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x03\x66\x65\x65\x18\x03 \x01(\x0b\x32\r.waves.Amount\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x0f\n\x07version\x18\x05 \x01(\x05\x12\x30\n\x07genesis\x18\x65 \x01(\x0b\x32\x1d.waves.GenesisTransactionDataH\x00\x12\x30\n\x07payment\x18\x66 \x01(\x0b\x32\x1d.waves.PaymentTransactionDataH\x00\x12,\n\x05issue\x18g \x01(\x0b\x32\x1b.waves.IssueTransactionDataH\x00\x12\x32\n\x08transfer\x18h \x01(\x0b\x32\x1e.waves.TransferTransactionDataH\x00\x12\x30\n\x07reissue\x18i \x01(\x0b\x32\x1d.waves.ReissueTransactionDataH\x00\x12*\n\x04\x62urn\x18j \x01(\x0b\x32\x1a.waves.BurnTransactionDataH\x00\x12\x32\n\x08\x65xchange\x18k \x01(\x0b\x32\x1e.waves.ExchangeTransactionDataH\x00\x12,\n\x05lease\x18l \x01(\x0b\x32\x1b.waves.LeaseTransactionDataH\x00\x12\x39\n\x0clease_cancel\x18m \x01(\x0b\x32!.waves.LeaseCancelTransactionDataH\x00\x12\x39\n\x0c\x63reate_alias\x18n \x01(\x0b\x32!.waves.CreateAliasTransactionDataH\x00\x12;\n\rmass_transfer\x18o \x01(\x0b\x32\".waves.MassTransferTransactionDataH\x00\x12\x36\n\x10\x64\x61ta_transaction\x18p \x01(\x0b\x32\x1a.waves.DataTransactionDataH\x00\x12\x35\n\nset_script\x18q \x01(\x0b\x32\x1f.waves.SetScriptTransactionDataH\x00\x12\x37\n\x0bsponsor_fee\x18r \x01(\x0b\x32 .waves.SponsorFeeTransactionDataH\x00\x12@\n\x10set_asset_script\x18s \x01(\x0b\x32$.waves.SetAssetScriptTransactionDataH\x00\x12;\n\rinvoke_script\x18t \x01(\x0b\x32\".waves.InvokeScriptTransactionDataH\x00\x12\x42\n\x11update_asset_info\x18u \x01(\x0b\x32%.waves.UpdateAssetInfoTransactionDataH\x00\x42\x06\n\x04\x64\x61ta\"C\n\x16GenesisTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"C\n\x16PaymentTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"u\n\nAttachment\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x03 \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x42\x0c\n\nattachment\"\x84\x01\n\x17TransferTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x1d\n\x06\x61mount\x18\x02 \x01(\x0b\x32\r.waves.Amount\x12%\n\nattachment\x18\x03 \x01(\x0b\x32\x11.waves.Attachment\"+\n\x1a\x43reateAliasTransactionData\x12\r\n\x05\x61lias\x18\x01 \x01(\t\"\xc7\x01\n\x13\x44\x61taTransactionData\x12\x32\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32$.waves.DataTransactionData.DataEntry\x1a|\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\n \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x0b \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x0c \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\r \x01(\tH\x00\x42\x07\n\x05value\"\xd5\x01\n\x1bMassTransferTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12>\n\ttransfers\x18\x02 \x03(\x0b\x32+.waves.MassTransferTransactionData.Transfer\x12%\n\nattachment\x18\x03 \x01(\x0b\x32\x11.waves.Attachment\x1a=\n\x08Transfer\x12!\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"K\n\x14LeaseTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\".\n\x1aLeaseCancelTransactionData\x12\x10\n\x08lease_id\x18\x01 \x01(\x0c\":\n\x13\x42urnTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\"\x7f\n\x14IssueTransactionData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x03\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x05\x12\x12\n\nreissuable\x18\x05 \x01(\x08\x12\x0e\n\x06script\x18\x06 \x01(\x0c\"Q\n\x16ReissueTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nreissuable\x18\x02 \x01(\x08\"A\n\x1dSetAssetScriptTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06script\x18\x02 \x01(\x0c\"*\n\x18SetScriptTransactionData\x12\x0e\n\x06script\x18\x01 \x01(\x0c\"\x89\x01\n\x17\x45xchangeTransactionData\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x03\x12\r\n\x05price\x18\x02 \x01(\x03\x12\x17\n\x0f\x62uy_matcher_fee\x18\x03 \x01(\x03\x12\x18\n\x10sell_matcher_fee\x18\x04 \x01(\x03\x12\x1c\n\x06orders\x18\x05 \x03(\x0b\x32\x0c.waves.Order\";\n\x19SponsorFeeTransactionData\x12\x1e\n\x07min_fee\x18\x01 \x01(\x0b\x32\r.waves.Amount\"v\n\x1bInvokeScriptTransactionData\x12\x1f\n\x05\x64_app\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x15\n\rfunction_call\x18\x02 \x01(\x0c\x12\x1f\n\x08payments\x18\x03 \x03(\x0b\x32\r.waves.Amount\"U\n\x1eUpdateAssetInfoTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\tB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' + , + dependencies=[amount__pb2.DESCRIPTOR,recipient__pb2.DESCRIPTOR,order__pb2.DESCRIPTOR,]) + + + + +_SIGNEDTRANSACTION = _descriptor.Descriptor( + name='SignedTransaction', + full_name='waves.SignedTransaction', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='transaction', full_name='waves.SignedTransaction.transaction', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proofs', full_name='waves.SignedTransaction.proofs', index=1, + number=2, type=12, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=72, + serialized_end=148, +) + + +_TRANSACTION = _descriptor.Descriptor( + name='Transaction', + full_name='waves.Transaction', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='chain_id', full_name='waves.Transaction.chain_id', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sender_public_key', full_name='waves.Transaction.sender_public_key', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fee', full_name='waves.Transaction.fee', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='timestamp', full_name='waves.Transaction.timestamp', index=3, + number=4, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='waves.Transaction.version', index=4, + number=5, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='genesis', full_name='waves.Transaction.genesis', index=5, + number=101, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payment', full_name='waves.Transaction.payment', index=6, + number=102, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='issue', full_name='waves.Transaction.issue', index=7, + number=103, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transfer', full_name='waves.Transaction.transfer', index=8, + number=104, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reissue', full_name='waves.Transaction.reissue', index=9, + number=105, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='burn', full_name='waves.Transaction.burn', index=10, + number=106, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='exchange', full_name='waves.Transaction.exchange', index=11, + number=107, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lease', full_name='waves.Transaction.lease', index=12, + number=108, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='lease_cancel', full_name='waves.Transaction.lease_cancel', index=13, + number=109, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='create_alias', full_name='waves.Transaction.create_alias', index=14, + number=110, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mass_transfer', full_name='waves.Transaction.mass_transfer', index=15, + number=111, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='data_transaction', full_name='waves.Transaction.data_transaction', index=16, + number=112, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='set_script', full_name='waves.Transaction.set_script', index=17, + number=113, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sponsor_fee', full_name='waves.Transaction.sponsor_fee', index=18, + number=114, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='set_asset_script', full_name='waves.Transaction.set_asset_script', index=19, + number=115, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='invoke_script', full_name='waves.Transaction.invoke_script', index=20, + number=116, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='update_asset_info', full_name='waves.Transaction.update_asset_info', index=21, + number=117, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='data', full_name='waves.Transaction.data', + index=0, containing_type=None, fields=[]), + ], + serialized_start=151, + serialized_end=1213, +) + + +_GENESISTRANSACTIONDATA = _descriptor.Descriptor( + name='GenesisTransactionData', + full_name='waves.GenesisTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='recipient_address', full_name='waves.GenesisTransactionData.recipient_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.GenesisTransactionData.amount', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1215, + serialized_end=1282, +) + + +_PAYMENTTRANSACTIONDATA = _descriptor.Descriptor( + name='PaymentTransactionData', + full_name='waves.PaymentTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='recipient_address', full_name='waves.PaymentTransactionData.recipient_address', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.PaymentTransactionData.amount', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1284, + serialized_end=1351, +) + + +_ATTACHMENT = _descriptor.Descriptor( + name='Attachment', + full_name='waves.Attachment', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='int_value', full_name='waves.Attachment.int_value', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_value', full_name='waves.Attachment.bool_value', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='binary_value', full_name='waves.Attachment.binary_value', index=2, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='waves.Attachment.string_value', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='attachment', full_name='waves.Attachment.attachment', + index=0, containing_type=None, fields=[]), + ], + serialized_start=1353, + serialized_end=1470, +) + + +_TRANSFERTRANSACTIONDATA = _descriptor.Descriptor( + name='TransferTransactionData', + full_name='waves.TransferTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='recipient', full_name='waves.TransferTransactionData.recipient', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.TransferTransactionData.amount', index=1, + number=2, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='attachment', full_name='waves.TransferTransactionData.attachment', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1473, + serialized_end=1605, +) + + +_CREATEALIASTRANSACTIONDATA = _descriptor.Descriptor( + name='CreateAliasTransactionData', + full_name='waves.CreateAliasTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='alias', full_name='waves.CreateAliasTransactionData.alias', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1607, + serialized_end=1650, +) + + +_DATATRANSACTIONDATA_DATAENTRY = _descriptor.Descriptor( + name='DataEntry', + full_name='waves.DataTransactionData.DataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='waves.DataTransactionData.DataEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_value', full_name='waves.DataTransactionData.DataEntry.int_value', index=1, + number=10, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='bool_value', full_name='waves.DataTransactionData.DataEntry.bool_value', index=2, + number=11, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='binary_value', full_name='waves.DataTransactionData.DataEntry.binary_value', index=3, + number=12, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='string_value', full_name='waves.DataTransactionData.DataEntry.string_value', index=4, + number=13, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='value', full_name='waves.DataTransactionData.DataEntry.value', + index=0, containing_type=None, fields=[]), + ], + serialized_start=1728, + serialized_end=1852, +) + +_DATATRANSACTIONDATA = _descriptor.Descriptor( + name='DataTransactionData', + full_name='waves.DataTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='data', full_name='waves.DataTransactionData.data', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_DATATRANSACTIONDATA_DATAENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1653, + serialized_end=1852, +) + + +_MASSTRANSFERTRANSACTIONDATA_TRANSFER = _descriptor.Descriptor( + name='Transfer', + full_name='waves.MassTransferTransactionData.Transfer', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='address', full_name='waves.MassTransferTransactionData.Transfer.address', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.MassTransferTransactionData.Transfer.amount', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2007, + serialized_end=2068, +) + +_MASSTRANSFERTRANSACTIONDATA = _descriptor.Descriptor( + name='MassTransferTransactionData', + full_name='waves.MassTransferTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_id', full_name='waves.MassTransferTransactionData.asset_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transfers', full_name='waves.MassTransferTransactionData.transfers', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='attachment', full_name='waves.MassTransferTransactionData.attachment', index=2, + number=3, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_MASSTRANSFERTRANSACTIONDATA_TRANSFER, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1855, + serialized_end=2068, +) + + +_LEASETRANSACTIONDATA = _descriptor.Descriptor( + name='LeaseTransactionData', + full_name='waves.LeaseTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='recipient', full_name='waves.LeaseTransactionData.recipient', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.LeaseTransactionData.amount', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2070, + serialized_end=2145, +) + + +_LEASECANCELTRANSACTIONDATA = _descriptor.Descriptor( + name='LeaseCancelTransactionData', + full_name='waves.LeaseCancelTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='lease_id', full_name='waves.LeaseCancelTransactionData.lease_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2147, + serialized_end=2193, +) + + +_BURNTRANSACTIONDATA = _descriptor.Descriptor( + name='BurnTransactionData', + full_name='waves.BurnTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_amount', full_name='waves.BurnTransactionData.asset_amount', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2195, + serialized_end=2253, +) + + +_ISSUETRANSACTIONDATA = _descriptor.Descriptor( + name='IssueTransactionData', + full_name='waves.IssueTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='name', full_name='waves.IssueTransactionData.name', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='description', full_name='waves.IssueTransactionData.description', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='amount', full_name='waves.IssueTransactionData.amount', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='decimals', full_name='waves.IssueTransactionData.decimals', index=3, + number=4, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reissuable', full_name='waves.IssueTransactionData.reissuable', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='script', full_name='waves.IssueTransactionData.script', index=5, + number=6, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2255, + serialized_end=2382, +) + + +_REISSUETRANSACTIONDATA = _descriptor.Descriptor( + name='ReissueTransactionData', + full_name='waves.ReissueTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_amount', full_name='waves.ReissueTransactionData.asset_amount', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='reissuable', full_name='waves.ReissueTransactionData.reissuable', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2384, + serialized_end=2465, +) + + +_SETASSETSCRIPTTRANSACTIONDATA = _descriptor.Descriptor( + name='SetAssetScriptTransactionData', + full_name='waves.SetAssetScriptTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_id', full_name='waves.SetAssetScriptTransactionData.asset_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='script', full_name='waves.SetAssetScriptTransactionData.script', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2467, + serialized_end=2532, +) + + +_SETSCRIPTTRANSACTIONDATA = _descriptor.Descriptor( + name='SetScriptTransactionData', + full_name='waves.SetScriptTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='script', full_name='waves.SetScriptTransactionData.script', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2534, + serialized_end=2576, +) + + +_EXCHANGETRANSACTIONDATA = _descriptor.Descriptor( + name='ExchangeTransactionData', + full_name='waves.ExchangeTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='amount', full_name='waves.ExchangeTransactionData.amount', index=0, + number=1, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='price', full_name='waves.ExchangeTransactionData.price', index=1, + number=2, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='buy_matcher_fee', full_name='waves.ExchangeTransactionData.buy_matcher_fee', index=2, + number=3, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sell_matcher_fee', full_name='waves.ExchangeTransactionData.sell_matcher_fee', index=3, + number=4, type=3, cpp_type=2, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='orders', full_name='waves.ExchangeTransactionData.orders', index=4, + number=5, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2579, + serialized_end=2716, +) + + +_SPONSORFEETRANSACTIONDATA = _descriptor.Descriptor( + name='SponsorFeeTransactionData', + full_name='waves.SponsorFeeTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='min_fee', full_name='waves.SponsorFeeTransactionData.min_fee', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2718, + serialized_end=2777, +) + + +_INVOKESCRIPTTRANSACTIONDATA = _descriptor.Descriptor( + name='InvokeScriptTransactionData', + full_name='waves.InvokeScriptTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='d_app', full_name='waves.InvokeScriptTransactionData.d_app', index=0, + number=1, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='function_call', full_name='waves.InvokeScriptTransactionData.function_call', index=1, + number=2, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='payments', full_name='waves.InvokeScriptTransactionData.payments', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2779, + serialized_end=2897, +) + + +_UPDATEASSETINFOTRANSACTIONDATA = _descriptor.Descriptor( + name='UpdateAssetInfoTransactionData', + full_name='waves.UpdateAssetInfoTransactionData', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='asset_id', full_name='waves.UpdateAssetInfoTransactionData.asset_id', index=0, + number=1, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='waves.UpdateAssetInfoTransactionData.name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='description', full_name='waves.UpdateAssetInfoTransactionData.description', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2899, + serialized_end=2984, +) + +_SIGNEDTRANSACTION.fields_by_name['transaction'].message_type = _TRANSACTION +_TRANSACTION.fields_by_name['fee'].message_type = amount__pb2._AMOUNT +_TRANSACTION.fields_by_name['genesis'].message_type = _GENESISTRANSACTIONDATA +_TRANSACTION.fields_by_name['payment'].message_type = _PAYMENTTRANSACTIONDATA +_TRANSACTION.fields_by_name['issue'].message_type = _ISSUETRANSACTIONDATA +_TRANSACTION.fields_by_name['transfer'].message_type = _TRANSFERTRANSACTIONDATA +_TRANSACTION.fields_by_name['reissue'].message_type = _REISSUETRANSACTIONDATA +_TRANSACTION.fields_by_name['burn'].message_type = _BURNTRANSACTIONDATA +_TRANSACTION.fields_by_name['exchange'].message_type = _EXCHANGETRANSACTIONDATA +_TRANSACTION.fields_by_name['lease'].message_type = _LEASETRANSACTIONDATA +_TRANSACTION.fields_by_name['lease_cancel'].message_type = _LEASECANCELTRANSACTIONDATA +_TRANSACTION.fields_by_name['create_alias'].message_type = _CREATEALIASTRANSACTIONDATA +_TRANSACTION.fields_by_name['mass_transfer'].message_type = _MASSTRANSFERTRANSACTIONDATA +_TRANSACTION.fields_by_name['data_transaction'].message_type = _DATATRANSACTIONDATA +_TRANSACTION.fields_by_name['set_script'].message_type = _SETSCRIPTTRANSACTIONDATA +_TRANSACTION.fields_by_name['sponsor_fee'].message_type = _SPONSORFEETRANSACTIONDATA +_TRANSACTION.fields_by_name['set_asset_script'].message_type = _SETASSETSCRIPTTRANSACTIONDATA +_TRANSACTION.fields_by_name['invoke_script'].message_type = _INVOKESCRIPTTRANSACTIONDATA +_TRANSACTION.fields_by_name['update_asset_info'].message_type = _UPDATEASSETINFOTRANSACTIONDATA +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['genesis']) +_TRANSACTION.fields_by_name['genesis'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['payment']) +_TRANSACTION.fields_by_name['payment'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['issue']) +_TRANSACTION.fields_by_name['issue'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['transfer']) +_TRANSACTION.fields_by_name['transfer'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['reissue']) +_TRANSACTION.fields_by_name['reissue'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['burn']) +_TRANSACTION.fields_by_name['burn'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['exchange']) +_TRANSACTION.fields_by_name['exchange'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['lease']) +_TRANSACTION.fields_by_name['lease'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['lease_cancel']) +_TRANSACTION.fields_by_name['lease_cancel'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['create_alias']) +_TRANSACTION.fields_by_name['create_alias'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['mass_transfer']) +_TRANSACTION.fields_by_name['mass_transfer'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['data_transaction']) +_TRANSACTION.fields_by_name['data_transaction'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['set_script']) +_TRANSACTION.fields_by_name['set_script'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['sponsor_fee']) +_TRANSACTION.fields_by_name['sponsor_fee'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['set_asset_script']) +_TRANSACTION.fields_by_name['set_asset_script'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['invoke_script']) +_TRANSACTION.fields_by_name['invoke_script'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_TRANSACTION.oneofs_by_name['data'].fields.append( + _TRANSACTION.fields_by_name['update_asset_info']) +_TRANSACTION.fields_by_name['update_asset_info'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] +_ATTACHMENT.oneofs_by_name['attachment'].fields.append( + _ATTACHMENT.fields_by_name['int_value']) +_ATTACHMENT.fields_by_name['int_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] +_ATTACHMENT.oneofs_by_name['attachment'].fields.append( + _ATTACHMENT.fields_by_name['bool_value']) +_ATTACHMENT.fields_by_name['bool_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] +_ATTACHMENT.oneofs_by_name['attachment'].fields.append( + _ATTACHMENT.fields_by_name['binary_value']) +_ATTACHMENT.fields_by_name['binary_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] +_ATTACHMENT.oneofs_by_name['attachment'].fields.append( + _ATTACHMENT.fields_by_name['string_value']) +_ATTACHMENT.fields_by_name['string_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] +_TRANSFERTRANSACTIONDATA.fields_by_name['recipient'].message_type = recipient__pb2._RECIPIENT +_TRANSFERTRANSACTIONDATA.fields_by_name['amount'].message_type = amount__pb2._AMOUNT +_TRANSFERTRANSACTIONDATA.fields_by_name['attachment'].message_type = _ATTACHMENT +_DATATRANSACTIONDATA_DATAENTRY.containing_type = _DATATRANSACTIONDATA +_DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'].fields.append( + _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['int_value']) +_DATATRANSACTIONDATA_DATAENTRY.fields_by_name['int_value'].containing_oneof = _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'] +_DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'].fields.append( + _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['bool_value']) +_DATATRANSACTIONDATA_DATAENTRY.fields_by_name['bool_value'].containing_oneof = _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'] +_DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'].fields.append( + _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['binary_value']) +_DATATRANSACTIONDATA_DATAENTRY.fields_by_name['binary_value'].containing_oneof = _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'] +_DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'].fields.append( + _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['string_value']) +_DATATRANSACTIONDATA_DATAENTRY.fields_by_name['string_value'].containing_oneof = _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'] +_DATATRANSACTIONDATA.fields_by_name['data'].message_type = _DATATRANSACTIONDATA_DATAENTRY +_MASSTRANSFERTRANSACTIONDATA_TRANSFER.fields_by_name['address'].message_type = recipient__pb2._RECIPIENT +_MASSTRANSFERTRANSACTIONDATA_TRANSFER.containing_type = _MASSTRANSFERTRANSACTIONDATA +_MASSTRANSFERTRANSACTIONDATA.fields_by_name['transfers'].message_type = _MASSTRANSFERTRANSACTIONDATA_TRANSFER +_MASSTRANSFERTRANSACTIONDATA.fields_by_name['attachment'].message_type = _ATTACHMENT +_LEASETRANSACTIONDATA.fields_by_name['recipient'].message_type = recipient__pb2._RECIPIENT +_BURNTRANSACTIONDATA.fields_by_name['asset_amount'].message_type = amount__pb2._AMOUNT +_REISSUETRANSACTIONDATA.fields_by_name['asset_amount'].message_type = amount__pb2._AMOUNT +_EXCHANGETRANSACTIONDATA.fields_by_name['orders'].message_type = order__pb2._ORDER +_SPONSORFEETRANSACTIONDATA.fields_by_name['min_fee'].message_type = amount__pb2._AMOUNT +_INVOKESCRIPTTRANSACTIONDATA.fields_by_name['d_app'].message_type = recipient__pb2._RECIPIENT +_INVOKESCRIPTTRANSACTIONDATA.fields_by_name['payments'].message_type = amount__pb2._AMOUNT +DESCRIPTOR.message_types_by_name['SignedTransaction'] = _SIGNEDTRANSACTION +DESCRIPTOR.message_types_by_name['Transaction'] = _TRANSACTION +DESCRIPTOR.message_types_by_name['GenesisTransactionData'] = _GENESISTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['PaymentTransactionData'] = _PAYMENTTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['Attachment'] = _ATTACHMENT +DESCRIPTOR.message_types_by_name['TransferTransactionData'] = _TRANSFERTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['CreateAliasTransactionData'] = _CREATEALIASTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['DataTransactionData'] = _DATATRANSACTIONDATA +DESCRIPTOR.message_types_by_name['MassTransferTransactionData'] = _MASSTRANSFERTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['LeaseTransactionData'] = _LEASETRANSACTIONDATA +DESCRIPTOR.message_types_by_name['LeaseCancelTransactionData'] = _LEASECANCELTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['BurnTransactionData'] = _BURNTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['IssueTransactionData'] = _ISSUETRANSACTIONDATA +DESCRIPTOR.message_types_by_name['ReissueTransactionData'] = _REISSUETRANSACTIONDATA +DESCRIPTOR.message_types_by_name['SetAssetScriptTransactionData'] = _SETASSETSCRIPTTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['SetScriptTransactionData'] = _SETSCRIPTTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['ExchangeTransactionData'] = _EXCHANGETRANSACTIONDATA +DESCRIPTOR.message_types_by_name['SponsorFeeTransactionData'] = _SPONSORFEETRANSACTIONDATA +DESCRIPTOR.message_types_by_name['InvokeScriptTransactionData'] = _INVOKESCRIPTTRANSACTIONDATA +DESCRIPTOR.message_types_by_name['UpdateAssetInfoTransactionData'] = _UPDATEASSETINFOTRANSACTIONDATA +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +SignedTransaction = _reflection.GeneratedProtocolMessageType('SignedTransaction', (_message.Message,), { + 'DESCRIPTOR' : _SIGNEDTRANSACTION, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.SignedTransaction) + }) +_sym_db.RegisterMessage(SignedTransaction) + +Transaction = _reflection.GeneratedProtocolMessageType('Transaction', (_message.Message,), { + 'DESCRIPTOR' : _TRANSACTION, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.Transaction) + }) +_sym_db.RegisterMessage(Transaction) + +GenesisTransactionData = _reflection.GeneratedProtocolMessageType('GenesisTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _GENESISTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.GenesisTransactionData) + }) +_sym_db.RegisterMessage(GenesisTransactionData) + +PaymentTransactionData = _reflection.GeneratedProtocolMessageType('PaymentTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _PAYMENTTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.PaymentTransactionData) + }) +_sym_db.RegisterMessage(PaymentTransactionData) + +Attachment = _reflection.GeneratedProtocolMessageType('Attachment', (_message.Message,), { + 'DESCRIPTOR' : _ATTACHMENT, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.Attachment) + }) +_sym_db.RegisterMessage(Attachment) + +TransferTransactionData = _reflection.GeneratedProtocolMessageType('TransferTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _TRANSFERTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.TransferTransactionData) + }) +_sym_db.RegisterMessage(TransferTransactionData) + +CreateAliasTransactionData = _reflection.GeneratedProtocolMessageType('CreateAliasTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _CREATEALIASTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.CreateAliasTransactionData) + }) +_sym_db.RegisterMessage(CreateAliasTransactionData) + +DataTransactionData = _reflection.GeneratedProtocolMessageType('DataTransactionData', (_message.Message,), { + + 'DataEntry' : _reflection.GeneratedProtocolMessageType('DataEntry', (_message.Message,), { + 'DESCRIPTOR' : _DATATRANSACTIONDATA_DATAENTRY, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.DataTransactionData.DataEntry) + }) + , + 'DESCRIPTOR' : _DATATRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.DataTransactionData) + }) +_sym_db.RegisterMessage(DataTransactionData) +_sym_db.RegisterMessage(DataTransactionData.DataEntry) + +MassTransferTransactionData = _reflection.GeneratedProtocolMessageType('MassTransferTransactionData', (_message.Message,), { + + 'Transfer' : _reflection.GeneratedProtocolMessageType('Transfer', (_message.Message,), { + 'DESCRIPTOR' : _MASSTRANSFERTRANSACTIONDATA_TRANSFER, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.MassTransferTransactionData.Transfer) + }) + , + 'DESCRIPTOR' : _MASSTRANSFERTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.MassTransferTransactionData) + }) +_sym_db.RegisterMessage(MassTransferTransactionData) +_sym_db.RegisterMessage(MassTransferTransactionData.Transfer) + +LeaseTransactionData = _reflection.GeneratedProtocolMessageType('LeaseTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _LEASETRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.LeaseTransactionData) + }) +_sym_db.RegisterMessage(LeaseTransactionData) + +LeaseCancelTransactionData = _reflection.GeneratedProtocolMessageType('LeaseCancelTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _LEASECANCELTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.LeaseCancelTransactionData) + }) +_sym_db.RegisterMessage(LeaseCancelTransactionData) + +BurnTransactionData = _reflection.GeneratedProtocolMessageType('BurnTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _BURNTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.BurnTransactionData) + }) +_sym_db.RegisterMessage(BurnTransactionData) + +IssueTransactionData = _reflection.GeneratedProtocolMessageType('IssueTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _ISSUETRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.IssueTransactionData) + }) +_sym_db.RegisterMessage(IssueTransactionData) + +ReissueTransactionData = _reflection.GeneratedProtocolMessageType('ReissueTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _REISSUETRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.ReissueTransactionData) + }) +_sym_db.RegisterMessage(ReissueTransactionData) + +SetAssetScriptTransactionData = _reflection.GeneratedProtocolMessageType('SetAssetScriptTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _SETASSETSCRIPTTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.SetAssetScriptTransactionData) + }) +_sym_db.RegisterMessage(SetAssetScriptTransactionData) + +SetScriptTransactionData = _reflection.GeneratedProtocolMessageType('SetScriptTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _SETSCRIPTTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.SetScriptTransactionData) + }) +_sym_db.RegisterMessage(SetScriptTransactionData) + +ExchangeTransactionData = _reflection.GeneratedProtocolMessageType('ExchangeTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _EXCHANGETRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.ExchangeTransactionData) + }) +_sym_db.RegisterMessage(ExchangeTransactionData) + +SponsorFeeTransactionData = _reflection.GeneratedProtocolMessageType('SponsorFeeTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _SPONSORFEETRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.SponsorFeeTransactionData) + }) +_sym_db.RegisterMessage(SponsorFeeTransactionData) + +InvokeScriptTransactionData = _reflection.GeneratedProtocolMessageType('InvokeScriptTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _INVOKESCRIPTTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.InvokeScriptTransactionData) + }) +_sym_db.RegisterMessage(InvokeScriptTransactionData) + +UpdateAssetInfoTransactionData = _reflection.GeneratedProtocolMessageType('UpdateAssetInfoTransactionData', (_message.Message,), { + 'DESCRIPTOR' : _UPDATEASSETINFOTRANSACTIONDATA, + '__module__' : 'transaction_pb2' + # @@protoc_insertion_point(class_scope:waves.UpdateAssetInfoTransactionData) + }) +_sym_db.RegisterMessage(UpdateAssetInfoTransactionData) + + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/src/main.c b/src/main.c index 55bb5ca4..d0a373c8 100644 --- a/src/main.c +++ b/src/main.c @@ -30,7 +30,17 @@ #include "os.h" #include "cx.h" #include "os_io_seproxyhal.h" - +#include "nanopb/pb_custom.h" +#include "nanopb/pb_decode.h" +#include "nanopb/pb_encode.h" +#include "nanopb_stubs/transaction.pb.h" + +#define OFFSET_CLA 0 +#define OFFSET_INS 1 +#define OFFSET_P1 2 +#define OFFSET_P2 3 +#define OFFSET_LC 4 +#define OFFSET_CDATA 5 // Temporary area to store stuff and reuse the same memory tmpContext_t tmp_ctx; uiContext_t ui_context; @@ -240,22 +250,64 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, if (tmp_ctx.signing_context.step == 5) { THROW(SW_INCORRECT_P1_P2); } - if (tmp_ctx.signing_context.step > 0) { tmp_ctx.signing_context.chunk += 1; } else { - show_processing(); + //show_processing(); os_memset((unsigned char *)&ui_context, 0, sizeof(uiContext_t)); tmp_ctx.signing_context.step = 1; tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; } - tmp_ctx.signing_context.chunk_used = 0; + uint8_t chunk_data_start_index = 5; + uint8_t chunk_data_size = G_io_apdu_buffer[4]; + + if (tmp_ctx.signing_context.chunk == 0) { + chunk_data_start_index += 28; + chunk_data_size -= 28; + + // then there is the bip32 path in the first chunk - first 20 bytes of data + read_path_from_bytes(G_io_apdu_buffer + 5, + (uint32_t *)tmp_ctx.signing_context.bip32); + + tmp_ctx.signing_context.amount_decimals = G_io_apdu_buffer[25]; + tmp_ctx.signing_context.fee_decimals = G_io_apdu_buffer[26]; + tmp_ctx.signing_context.data_type = G_io_apdu_buffer[27]; + tmp_ctx.signing_context.data_version = G_io_apdu_buffer[28]; + tmp_ctx.signing_context.data_size = + deserialize_uint32_t(&G_io_apdu_buffer[29]); + } + + uint8_t status; + uint16_t total_message_size = tmp_ctx.signing_context.data_size; + + PRINTF("total_message_size: %d\n", total_message_size); + + pb_istream_from_apdu_ctx_t pb_apdu_ctx; + + waves_Transaction tx = waves_Transaction_init_zero; + + /* Create an input stream that will deserialize the nanopb message coming from successives APDUs */ + pb_istream_t stream = pb_istream_from_apdu(&pb_apdu_ctx, G_io_apdu_buffer + chunk_data_start_index, G_io_apdu_buffer[4] - chunk_data_start_index + 5, total_message_size); + + /* Now we are ready to decode the message. */ + status = pb_decode(&stream, waves_Transaction_fields, &tx); + /* Check for errors... */ + if (!status) + { + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + THROW(0x6D00); + } + + THROW(0x9000); + break; + + /*tmp_ctx.signing_context.chunk_used = 0; ui_context.chunk_used = 0; if (G_io_apdu_buffer[2] == P1_LAST) { make_allowed_sign_steps(); if (tmp_ctx.signing_context.step == 5) { - make_allowed_ui_steps(true); + //make_allowed_ui_steps(true); show_sign_ui(); *flags |= IO_ASYNCH_REPLY; } else { @@ -263,9 +315,9 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } } else { make_allowed_sign_steps(); - make_allowed_ui_steps(false); + //make_allowed_ui_steps(false); THROW(SW_OK); - } + }*/ } break; diff --git a/src/main.h b/src/main.h index 813ca30f..9b5d5e48 100644 --- a/src/main.h +++ b/src/main.h @@ -34,6 +34,7 @@ #define P1_NON_CONFIRM 0x00 // Don't show address confirmation #define P1_LAST 0x80 // Parameter 1 = End of Bytes to Sign (finalize) #define P1_MORE 0x00 // Parameter 1 = More bytes coming +#define PB_FIRST_BYTE 0x0A //First byte of protobuf transaction message #define SW_OK 0x9000 #define SW_USER_CANCELLED 0x9100 diff --git a/src/ui/nanopb/pb.h b/src/nanopb/pb.h similarity index 100% rename from src/ui/nanopb/pb.h rename to src/nanopb/pb.h diff --git a/src/ui/nanopb/pb_common.c b/src/nanopb/pb_common.c similarity index 100% rename from src/ui/nanopb/pb_common.c rename to src/nanopb/pb_common.c diff --git a/src/ui/nanopb/pb_common.h b/src/nanopb/pb_common.h similarity index 100% rename from src/ui/nanopb/pb_common.h rename to src/nanopb/pb_common.h diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c new file mode 100644 index 00000000..1b95bf2c --- /dev/null +++ b/src/nanopb/pb_custom.c @@ -0,0 +1,155 @@ +#include "pb_custom.h" +#include "os.h" +#include "pb_decode.h" + +/******************************************************* + * Ledger's APDU pb_istream_from_apdu_t implementation * + *******************************************************/ +#define OFFSET_P1 2 +#define OFFSET_LC 4 +#define OFFSET_DATA 5 +#define P1_FIRST 0x00 +#define P1_NEXT 0x80 + +#define MAX_FETCH_ATTEMPTS 10 + +#define ERR_PB_READ_IS_TOO_BIG 0x6002 +#define ERR_NOT_ENOUGH_BYTES_RECEIVED 0x6003 +#define ERR_BUFFER_TOO_SMALL 0x6005 +#define ERR_WRONG_MESSAGE_SIZE 0x6006 +#define ERR_WRONG_PARAMETER 0x6007 + +//#define PRINTF_PB(...) //PRINTF(__VA_ARGS__) + +#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + #define checkreturn +#else + #define checkreturn __attribute__((warn_unused_result)) +#endif + +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; + + +void inline fetch_new_apdu(pb_istream_from_apdu_ctx_t *state) __attribute__((no_instrument_function)); + +void fetch_new_apdu(pb_istream_from_apdu_ctx_t *state){ + + unsigned int rx; + G_io_apdu_buffer[0] = 0x90; + G_io_apdu_buffer[1] = 0x00; + rx = io_exchange(CHANNEL_APDU, 2); + + if(G_io_apdu_buffer[OFFSET_P1] != P1_NEXT){ + THROW(ERR_WRONG_PARAMETER); + } + else if(state->bytes_stored + G_io_apdu_buffer[OFFSET_LC] > sizeof(state->data)){ + PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, G_io_apdu_buffer[OFFSET_LC]); + THROW(ERR_BUFFER_TOO_SMALL); + } + + state->total_received += G_io_apdu_buffer[OFFSET_LC]; + + if (state->total_received > state->total_size) + { + PRINTF("total_rec: %d total_size %d\n", state->total_received , state->total_size); + THROW(ERR_WRONG_MESSAGE_SIZE); + } + +} + +bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) +{ + pb_istream_from_apdu_ctx_t *state; + uint16_t bytes_not_read_yet; + uint8_t fetch_attempts; + const pb_byte_t *source; + + if(count > MAX_PB_ELEMENT_SIZE){ + THROW(ERR_PB_READ_IS_TOO_BIG); + } + + state = (pb_istream_from_apdu_ctx_t*)stream->state; + + bytes_not_read_yet = state->bytes_stored-state->read_offset; + + PRINTF("read: %d readable: %d stored %d\n", count, bytes_not_read_yet, state->bytes_stored); + + /* not enough data has been received and deciphered, we fetch a new apdu or stop the s + tream if the last apdu was already received*/ + if(count > bytes_not_read_yet){ + // shift data to the beginning of the buffer + os_memmove(state->data, state->data+state->read_offset, state->bytes_stored - state->read_offset); + state->bytes_stored = bytes_not_read_yet; + state->read_offset = 0; + + PRINTF("SHIFT LEFT: available: %d\n", bytes_not_read_yet); + + // loop over apdu fetching while there's not enough bytes stored to feed the amount requested + fetch_attempts = 0; + while(count > bytes_not_read_yet){ + + if (++fetch_attempts > MAX_FETCH_ATTEMPTS) + { + THROW(ERR_NOT_ENOUGH_BYTES_RECEIVED); + } + else if(state->total_received == state->total_size){ + // Everything has been received, signal to nanopb that it's time to end decoding + stream->bytes_left = 0; + return false; + } + + fetch_new_apdu(state); + + os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + OFFSET_DATA, G_io_apdu_buffer[OFFSET_LC]); + + state->bytes_stored += G_io_apdu_buffer[OFFSET_LC]; + bytes_not_read_yet = state->bytes_stored - state->read_offset; + } + } + + // extract data to output buffer + source = (const pb_byte_t*)state->data + state->read_offset; + state->read_offset += count; + + if (buf != NULL) + { + for (uint16_t i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; +} + +/* + Returns a nanopb input stream handler that feeds data from APDUs + ctx: istream state that stores information about io context + init_buffer: initialized the stream with some data (can be set to NULL) + init_buffer_size: length of init_buffer + total_buffer_size: total length of the message to receive +*/ +pb_istream_t pb_istream_from_apdu(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size) +{ + pb_istream_t stream; + + stream.callback = &apdu_read;; + + stream.state = ctx; + stream.bytes_left = SIZE_MAX; +#ifndef PB_NO_ERRMSG + stream.errmsg = NULL; +#endif + os_memset(ctx, 0, sizeof(pb_istream_from_apdu_ctx_t)); + PRINTF("Init buffer:\n%.*H\n", init_buffer_size, init_buffer); + ctx->total_received = init_buffer_size; + ctx->total_size = total_buffer_size; + os_memmove(ctx->data, init_buffer, init_buffer_size); + ctx->bytes_stored = init_buffer_size; + ctx->read_offset = 0; + +#ifdef HAVE_PRINTF + // Set call stack monitoring level to 0 + G_depth = 0; +#endif + + return stream; +} \ No newline at end of file diff --git a/src/nanopb/pb_custom.h b/src/nanopb/pb_custom.h new file mode 100644 index 00000000..9a454560 --- /dev/null +++ b/src/nanopb/pb_custom.h @@ -0,0 +1,31 @@ +#ifndef _PB_CUSTOM_ +#define _PB_CUSTOM_ + +#include "stdint.h" +#include "os.h" +#include "cx.h" +#include "pb.h" + + +/* Custom `pb_istream_s.state` structure that handles decoding from apdu streaming */ +#define PB_DECODING_FAILED 0 +// Maximum size of a single serialized pb element +#define MAX_PB_ELEMENT_SIZE 100 +// Maximum size of an APDU payload. Can be reduced to save some bytes, but then the host has to ensure that it doesn't send APDU payloads bigger than this value. +#define MAX_APDU_PAYLOAD_SIZE 255 + + +typedef struct{ + uint8_t data[MAX_PB_ELEMENT_SIZE + MAX_APDU_PAYLOAD_SIZE]; // size of the biggest nanopb element serialized + size of an APDU (worst case scenario) + uint32_t read_offset; // nanopb read offset, everything before it has been succesfully decoded + uint32_t bytes_stored; // number of bytes currently stored in "data" + uint32_t total_size; // total size of the nanopb structure being received + uint32_t total_received; // number of bytes received since decoding began + +} pb_istream_from_apdu_ctx_t; + + +pb_istream_t apdu_pb_istream(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size); +pb_istream_t pb_istream_from_apdu(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size); + +#endif \ No newline at end of file diff --git a/src/ui/nanopb/pb_decode.c b/src/nanopb/pb_decode.c similarity index 100% rename from src/ui/nanopb/pb_decode.c rename to src/nanopb/pb_decode.c diff --git a/src/ui/nanopb/pb_decode.h b/src/nanopb/pb_decode.h similarity index 100% rename from src/ui/nanopb/pb_decode.h rename to src/nanopb/pb_decode.h diff --git a/src/ui/nanopb/pb_encode.c b/src/nanopb/pb_encode.c similarity index 100% rename from src/ui/nanopb/pb_encode.c rename to src/nanopb/pb_encode.c diff --git a/src/ui/nanopb/pb_encode.h b/src/nanopb/pb_encode.h similarity index 100% rename from src/ui/nanopb/pb_encode.h rename to src/nanopb/pb_encode.h diff --git a/src/nanopb_stubs/amount.pb.c b/src/nanopb_stubs/amount.pb.c new file mode 100644 index 00000000..29524eec --- /dev/null +++ b/src/nanopb_stubs/amount.pb.c @@ -0,0 +1,20 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#include "amount.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t waves_Amount_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_Amount, asset_id, asset_id, 0), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_Amount, amount, asset_id, 0), + PB_LAST_FIELD +}; + + +/* @@protoc_insertion_point(eof) */ diff --git a/src/ui/nanopb/simple.pb.h b/src/nanopb_stubs/amount.pb.h similarity index 51% rename from src/ui/nanopb/simple.pb.h rename to src/nanopb_stubs/amount.pb.h index e94e8ceb..09db2cf6 100644 --- a/src/ui/nanopb/simple.pb.h +++ b/src/nanopb_stubs/amount.pb.h @@ -1,8 +1,8 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.3 at Tue Apr 7 15:35:57 2020. */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ -#ifndef PB_SIMPLE_PB_H_INCLUDED -#define PB_SIMPLE_PB_H_INCLUDED +#ifndef PB_WAVES_AMOUNT_PB_H_INCLUDED +#define PB_WAVES_AMOUNT_PB_H_INCLUDED #include /* @@protoc_insertion_point(includes) */ @@ -15,30 +15,32 @@ extern "C" { #endif /* Struct definitions */ -typedef struct _SimpleMessage { - int32_t lucky_number; -/* @@protoc_insertion_point(struct:SimpleMessage) */ -} SimpleMessage; +typedef struct _waves_Amount { + pb_callback_t asset_id; + int64_t amount; +/* @@protoc_insertion_point(struct:waves_Amount) */ +} waves_Amount; /* Default values for struct fields */ /* Initializer values for message structs */ -#define SimpleMessage_init_default {0} -#define SimpleMessage_init_zero {0} +#define waves_Amount_init_default {{{NULL}, NULL}, 0} +#define waves_Amount_init_zero {{{NULL}, NULL}, 0} /* Field tags (for use in manual encoding/decoding) */ -#define SimpleMessage_lucky_number_tag 1 +#define waves_Amount_asset_id_tag 1 +#define waves_Amount_amount_tag 2 /* Struct field encoding specification for nanopb */ -extern const pb_field_t SimpleMessage_fields[2]; +extern const pb_field_t waves_Amount_fields[3]; /* Maximum encoded size of messages (where known) */ -#define SimpleMessage_size 11 +/* waves_Amount_size depends on runtime parameters */ /* Message IDs (where set with "msgid" option) */ #ifdef PB_MSGID -#define SIMPLE_MESSAGES \ +#define AMOUNT_MESSAGES \ #endif diff --git a/src/nanopb_stubs/order.pb.c b/src/nanopb_stubs/order.pb.c new file mode 100644 index 00000000..81679cf2 --- /dev/null +++ b/src/nanopb_stubs/order.pb.c @@ -0,0 +1,61 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#include "order.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t waves_AssetPair_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_AssetPair, amount_asset_id, amount_asset_id, 0), + PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_AssetPair, price_asset_id, amount_asset_id, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_Order_fields[13] = { + PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, waves_Order, chain_id, chain_id, 0), + PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_Order, sender_public_key, chain_id, 0), + PB_FIELD( 3, BYTES , SINGULAR, CALLBACK, OTHER, waves_Order, matcher_public_key, sender_public_key, 0), + PB_FIELD( 4, MESSAGE , SINGULAR, STATIC , OTHER, waves_Order, asset_pair, matcher_public_key, &waves_AssetPair_fields), + PB_FIELD( 5, UENUM , SINGULAR, STATIC , OTHER, waves_Order, order_side, asset_pair, 0), + PB_FIELD( 6, INT64 , SINGULAR, STATIC , OTHER, waves_Order, amount, order_side, 0), + PB_FIELD( 7, INT64 , SINGULAR, STATIC , OTHER, waves_Order, price, amount, 0), + PB_FIELD( 8, INT64 , SINGULAR, STATIC , OTHER, waves_Order, timestamp, price, 0), + PB_FIELD( 9, INT64 , SINGULAR, STATIC , OTHER, waves_Order, expiration, timestamp, 0), + PB_FIELD( 10, MESSAGE , SINGULAR, STATIC , OTHER, waves_Order, matcher_fee, expiration, &waves_Amount_fields), + PB_FIELD( 11, INT32 , SINGULAR, STATIC , OTHER, waves_Order, version, matcher_fee, 0), + PB_FIELD( 12, BYTES , REPEATED, CALLBACK, OTHER, waves_Order, proofs, version, 0), + PB_LAST_FIELD +}; + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(waves_Order, asset_pair) < 65536 && pb_membersize(waves_Order, matcher_fee) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_waves_AssetPair_waves_Order) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(waves_Order, asset_pair) < 256 && pb_membersize(waves_Order, matcher_fee) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_waves_AssetPair_waves_Order) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/src/nanopb_stubs/order.pb.h b/src/nanopb_stubs/order.pb.h new file mode 100644 index 00000000..23cd3d4b --- /dev/null +++ b/src/nanopb_stubs/order.pb.h @@ -0,0 +1,96 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#ifndef PB_WAVES_ORDER_PB_H_INCLUDED +#define PB_WAVES_ORDER_PB_H_INCLUDED +#include + +#include "amount.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Enum definitions */ +typedef enum _waves_Order_Side { + waves_Order_Side_BUY = 0, + waves_Order_Side_SELL = 1 +} waves_Order_Side; +#define _waves_Order_Side_MIN waves_Order_Side_BUY +#define _waves_Order_Side_MAX waves_Order_Side_SELL +#define _waves_Order_Side_ARRAYSIZE ((waves_Order_Side)(waves_Order_Side_SELL+1)) + +/* Struct definitions */ +typedef struct _waves_AssetPair { + pb_callback_t amount_asset_id; + pb_callback_t price_asset_id; +/* @@protoc_insertion_point(struct:waves_AssetPair) */ +} waves_AssetPair; + +typedef struct _waves_Order { + int32_t chain_id; + pb_callback_t sender_public_key; + pb_callback_t matcher_public_key; + waves_AssetPair asset_pair; + waves_Order_Side order_side; + int64_t amount; + int64_t price; + int64_t timestamp; + int64_t expiration; + waves_Amount matcher_fee; + int32_t version; + pb_callback_t proofs; +/* @@protoc_insertion_point(struct:waves_Order) */ +} waves_Order; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define waves_AssetPair_init_default {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_Order_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}, waves_AssetPair_init_default, _waves_Order_Side_MIN, 0, 0, 0, 0, waves_Amount_init_default, 0, {{NULL}, NULL}} +#define waves_AssetPair_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_Order_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}, waves_AssetPair_init_zero, _waves_Order_Side_MIN, 0, 0, 0, 0, waves_Amount_init_zero, 0, {{NULL}, NULL}} + +/* Field tags (for use in manual encoding/decoding) */ +#define waves_AssetPair_amount_asset_id_tag 1 +#define waves_AssetPair_price_asset_id_tag 2 +#define waves_Order_chain_id_tag 1 +#define waves_Order_sender_public_key_tag 2 +#define waves_Order_matcher_public_key_tag 3 +#define waves_Order_asset_pair_tag 4 +#define waves_Order_order_side_tag 5 +#define waves_Order_amount_tag 6 +#define waves_Order_price_tag 7 +#define waves_Order_timestamp_tag 8 +#define waves_Order_expiration_tag 9 +#define waves_Order_matcher_fee_tag 10 +#define waves_Order_version_tag 11 +#define waves_Order_proofs_tag 12 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t waves_AssetPair_fields[3]; +extern const pb_field_t waves_Order_fields[13]; + +/* Maximum encoded size of messages (where known) */ +/* waves_AssetPair_size depends on runtime parameters */ +/* waves_Order_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define ORDER_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/src/nanopb_stubs/recipient.pb.c b/src/nanopb_stubs/recipient.pb.c new file mode 100644 index 00000000..927abc58 --- /dev/null +++ b/src/nanopb_stubs/recipient.pb.c @@ -0,0 +1,20 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#include "recipient.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t waves_Recipient_fields[3] = { + PB_ONEOF_FIELD(recipient, 1, BYTES , ONEOF, STATIC , FIRST, waves_Recipient, public_key_hash, public_key_hash, 0), + PB_ONEOF_FIELD(recipient, 2, STRING , ONEOF, STATIC , UNION, waves_Recipient, alias, alias, 0), + PB_LAST_FIELD +}; + + +/* @@protoc_insertion_point(eof) */ diff --git a/src/nanopb_stubs/recipient.pb.h b/src/nanopb_stubs/recipient.pb.h new file mode 100644 index 00000000..1e4c3a3d --- /dev/null +++ b/src/nanopb_stubs/recipient.pb.h @@ -0,0 +1,57 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#ifndef PB_WAVES_RECIPIENT_PB_H_INCLUDED +#define PB_WAVES_RECIPIENT_PB_H_INCLUDED +#include + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(26) waves_Recipient_public_key_hash_t; +typedef struct _waves_Recipient { + pb_size_t which_recipient; + union { + waves_Recipient_public_key_hash_t public_key_hash; + char alias[34]; + } recipient; +/* @@protoc_insertion_point(struct:waves_Recipient) */ +} waves_Recipient; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define waves_Recipient_init_default {0, {{0, {0}}}} +#define waves_Recipient_init_zero {0, {{0, {0}}}} + +/* Field tags (for use in manual encoding/decoding) */ +#define waves_Recipient_public_key_hash_tag 1 +#define waves_Recipient_alias_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t waves_Recipient_fields[3]; + +/* Maximum encoded size of messages (where known) */ +#define waves_Recipient_size 36 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define RECIPIENT_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/src/nanopb_stubs/transaction.pb.c b/src/nanopb_stubs/transaction.pb.c new file mode 100644 index 00000000..6f5b4f6d --- /dev/null +++ b/src/nanopb_stubs/transaction.pb.c @@ -0,0 +1,193 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#include "transaction.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t waves_SignedTransaction_fields[3] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_SignedTransaction, transaction, transaction, &waves_Transaction_fields), + PB_FIELD( 2, BYTES , REPEATED, CALLBACK, OTHER, waves_SignedTransaction, proofs, transaction, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_Transaction_fields[23] = { + PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, waves_Transaction, chain_id, chain_id, 0), + PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_Transaction, sender_public_key, chain_id, 0), + PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_Transaction, fee, sender_public_key, &waves_Amount_fields), + PB_FIELD( 4, INT64 , SINGULAR, STATIC , OTHER, waves_Transaction, timestamp, fee, 0), + PB_FIELD( 5, INT32 , SINGULAR, STATIC , OTHER, waves_Transaction, version, timestamp, 0), + PB_ONEOF_FIELD(data, 101, MESSAGE , ONEOF, STATIC , OTHER, waves_Transaction, genesis, version, &waves_GenesisTransactionData_fields), + PB_ONEOF_FIELD(data, 102, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, payment, version, &waves_PaymentTransactionData_fields), + PB_ONEOF_FIELD(data, 103, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, issue, version, &waves_IssueTransactionData_fields), + PB_ONEOF_FIELD(data, 104, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, transfer, version, &waves_TransferTransactionData_fields), + PB_ONEOF_FIELD(data, 105, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, reissue, version, &waves_ReissueTransactionData_fields), + PB_ONEOF_FIELD(data, 106, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, burn, version, &waves_BurnTransactionData_fields), + PB_ONEOF_FIELD(data, 107, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, exchange, version, &waves_ExchangeTransactionData_fields), + PB_ONEOF_FIELD(data, 108, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, lease, version, &waves_LeaseTransactionData_fields), + PB_ONEOF_FIELD(data, 109, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, lease_cancel, version, &waves_LeaseCancelTransactionData_fields), + PB_ONEOF_FIELD(data, 110, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, create_alias, version, &waves_CreateAliasTransactionData_fields), + PB_ONEOF_FIELD(data, 111, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, mass_transfer, version, &waves_MassTransferTransactionData_fields), + PB_ONEOF_FIELD(data, 112, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, data_transaction, version, &waves_DataTransactionData_fields), + PB_ONEOF_FIELD(data, 113, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, set_script, version, &waves_SetScriptTransactionData_fields), + PB_ONEOF_FIELD(data, 114, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, sponsor_fee, version, &waves_SponsorFeeTransactionData_fields), + PB_ONEOF_FIELD(data, 115, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, set_asset_script, version, &waves_SetAssetScriptTransactionData_fields), + PB_ONEOF_FIELD(data, 116, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, invoke_script, version, &waves_InvokeScriptTransactionData_fields), + PB_ONEOF_FIELD(data, 117, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, update_asset_info, version, &waves_UpdateAssetInfoTransactionData_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_GenesisTransactionData_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_GenesisTransactionData, recipient_address, recipient_address, 0), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_GenesisTransactionData, amount, recipient_address, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_PaymentTransactionData_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_PaymentTransactionData, recipient_address, recipient_address, 0), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_PaymentTransactionData, amount, recipient_address, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_Attachment_fields[5] = { + PB_ONEOF_FIELD(attachment, 1, INT64 , ONEOF, STATIC , FIRST, waves_Attachment, int_value, int_value, 0), + PB_ONEOF_FIELD(attachment, 2, BOOL , ONEOF, STATIC , UNION, waves_Attachment, bool_value, bool_value, 0), + PB_ONEOF_FIELD(attachment, 3, BYTES , ONEOF, STATIC , UNION, waves_Attachment, binary_value, binary_value, 0), + PB_ONEOF_FIELD(attachment, 4, STRING , ONEOF, STATIC , UNION, waves_Attachment, string_value, string_value, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_TransferTransactionData_fields[4] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_TransferTransactionData, recipient, recipient, &waves_Recipient_fields), + PB_FIELD( 2, MESSAGE , SINGULAR, STATIC , OTHER, waves_TransferTransactionData, amount, recipient, &waves_Amount_fields), + PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_TransferTransactionData, attachment, amount, &waves_Attachment_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_CreateAliasTransactionData_fields[2] = { + PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_CreateAliasTransactionData, alias, alias, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_DataTransactionData_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, waves_DataTransactionData, data, data, &waves_DataTransactionData_DataEntry_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_DataTransactionData_DataEntry_fields[6] = { + PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_DataTransactionData_DataEntry, key, key, 0), + PB_ONEOF_FIELD(value, 10, INT64 , ONEOF, STATIC , OTHER, waves_DataTransactionData_DataEntry, int_value, key, 0), + PB_ONEOF_FIELD(value, 11, BOOL , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, bool_value, key, 0), + PB_ONEOF_FIELD(value, 12, BYTES , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, binary_value, key, 0), + PB_ONEOF_FIELD(value, 13, STRING , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, string_value, key, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_MassTransferTransactionData_fields[4] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_MassTransferTransactionData, asset_id, asset_id, 0), + PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, waves_MassTransferTransactionData, transfers, asset_id, &waves_MassTransferTransactionData_Transfer_fields), + PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_MassTransferTransactionData, attachment, transfers, &waves_Attachment_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_MassTransferTransactionData_Transfer_fields[3] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_MassTransferTransactionData_Transfer, address, address, &waves_Recipient_fields), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_MassTransferTransactionData_Transfer, amount, address, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_LeaseTransactionData_fields[3] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_LeaseTransactionData, recipient, recipient, &waves_Recipient_fields), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_LeaseTransactionData, amount, recipient, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_LeaseCancelTransactionData_fields[2] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_LeaseCancelTransactionData, lease_id, lease_id, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_BurnTransactionData_fields[2] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_BurnTransactionData, asset_amount, asset_amount, &waves_Amount_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_IssueTransactionData_fields[7] = { + PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_IssueTransactionData, name, name, 0), + PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, waves_IssueTransactionData, description, name, 0), + PB_FIELD( 3, INT64 , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, amount, description, 0), + PB_FIELD( 4, INT32 , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, decimals, amount, 0), + PB_FIELD( 5, BOOL , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, reissuable, decimals, 0), + PB_FIELD( 6, BYTES , SINGULAR, CALLBACK, OTHER, waves_IssueTransactionData, script, reissuable, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_ReissueTransactionData_fields[3] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_ReissueTransactionData, asset_amount, asset_amount, &waves_Amount_fields), + PB_FIELD( 2, BOOL , SINGULAR, STATIC , OTHER, waves_ReissueTransactionData, reissuable, asset_amount, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_SetAssetScriptTransactionData_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_SetAssetScriptTransactionData, asset_id, asset_id, 0), + PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_SetAssetScriptTransactionData, script, asset_id, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_SetScriptTransactionData_fields[2] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_SetScriptTransactionData, script, script, 0), + PB_LAST_FIELD +}; + +const pb_field_t waves_ExchangeTransactionData_fields[6] = { + PB_FIELD( 1, INT64 , SINGULAR, STATIC , FIRST, waves_ExchangeTransactionData, amount, amount, 0), + PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, price, amount, 0), + PB_FIELD( 3, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, buy_matcher_fee, price, 0), + PB_FIELD( 4, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, sell_matcher_fee, buy_matcher_fee, 0), + PB_FIELD( 5, MESSAGE , REPEATED, CALLBACK, OTHER, waves_ExchangeTransactionData, orders, sell_matcher_fee, &waves_Order_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_SponsorFeeTransactionData_fields[2] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_SponsorFeeTransactionData, min_fee, min_fee, &waves_Amount_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_InvokeScriptTransactionData_fields[4] = { + PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_InvokeScriptTransactionData, d_app, d_app, &waves_Recipient_fields), + PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_InvokeScriptTransactionData, function_call, d_app, 0), + PB_FIELD( 3, MESSAGE , REPEATED, CALLBACK, OTHER, waves_InvokeScriptTransactionData, payments, function_call, &waves_Amount_fields), + PB_LAST_FIELD +}; + +const pb_field_t waves_UpdateAssetInfoTransactionData_fields[4] = { + PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_UpdateAssetInfoTransactionData, asset_id, asset_id, 0), + PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, waves_UpdateAssetInfoTransactionData, name, asset_id, 0), + PB_FIELD( 3, STRING , SINGULAR, CALLBACK, OTHER, waves_UpdateAssetInfoTransactionData, description, name, 0), + PB_LAST_FIELD +}; + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(waves_SignedTransaction, transaction) < 65536 && pb_membersize(waves_Transaction, data.genesis) < 65536 && pb_membersize(waves_Transaction, data.payment) < 65536 && pb_membersize(waves_Transaction, data.issue) < 65536 && pb_membersize(waves_Transaction, data.transfer) < 65536 && pb_membersize(waves_Transaction, data.reissue) < 65536 && pb_membersize(waves_Transaction, data.burn) < 65536 && pb_membersize(waves_Transaction, data.exchange) < 65536 && pb_membersize(waves_Transaction, data.lease) < 65536 && pb_membersize(waves_Transaction, data.lease_cancel) < 65536 && pb_membersize(waves_Transaction, data.create_alias) < 65536 && pb_membersize(waves_Transaction, data.mass_transfer) < 65536 && pb_membersize(waves_Transaction, data.data_transaction) < 65536 && pb_membersize(waves_Transaction, data.set_script) < 65536 && pb_membersize(waves_Transaction, data.sponsor_fee) < 65536 && pb_membersize(waves_Transaction, data.set_asset_script) < 65536 && pb_membersize(waves_Transaction, data.invoke_script) < 65536 && pb_membersize(waves_Transaction, data.update_asset_info) < 65536 && pb_membersize(waves_Transaction, fee) < 65536 && pb_membersize(waves_TransferTransactionData, recipient) < 65536 && pb_membersize(waves_TransferTransactionData, amount) < 65536 && pb_membersize(waves_TransferTransactionData, attachment) < 65536 && pb_membersize(waves_DataTransactionData_DataEntry, value.binary_value) < 65536 && pb_membersize(waves_MassTransferTransactionData, attachment) < 65536 && pb_membersize(waves_MassTransferTransactionData_Transfer, address) < 65536 && pb_membersize(waves_LeaseTransactionData, recipient) < 65536 && pb_membersize(waves_BurnTransactionData, asset_amount) < 65536 && pb_membersize(waves_ReissueTransactionData, asset_amount) < 65536 && pb_membersize(waves_SponsorFeeTransactionData, min_fee) < 65536 && pb_membersize(waves_InvokeScriptTransactionData, d_app) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_waves_SignedTransaction_waves_Transaction_waves_GenesisTransactionData_waves_PaymentTransactionData_waves_Attachment_waves_TransferTransactionData_waves_CreateAliasTransactionData_waves_DataTransactionData_waves_DataTransactionData_DataEntry_waves_MassTransferTransactionData_waves_MassTransferTransactionData_Transfer_waves_LeaseTransactionData_waves_LeaseCancelTransactionData_waves_BurnTransactionData_waves_IssueTransactionData_waves_ReissueTransactionData_waves_SetAssetScriptTransactionData_waves_SetScriptTransactionData_waves_ExchangeTransactionData_waves_SponsorFeeTransactionData_waves_InvokeScriptTransactionData_waves_UpdateAssetInfoTransactionData) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +#error Field descriptor for waves_DataTransactionData_DataEntry.string_value is too large. Define PB_FIELD_16BIT to fix this. +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/src/nanopb_stubs/transaction.pb.h b/src/nanopb_stubs/transaction.pb.h new file mode 100644 index 00000000..73c1f44c --- /dev/null +++ b/src/nanopb_stubs/transaction.pb.h @@ -0,0 +1,382 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ + +#ifndef PB_WAVES_TRANSACTION_PB_H_INCLUDED +#define PB_WAVES_TRANSACTION_PB_H_INCLUDED +#include + +#include "amount.pb.h" + +#include "recipient.pb.h" + +#include "order.pb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Struct definitions */ +typedef struct _waves_CreateAliasTransactionData { + pb_callback_t alias; +/* @@protoc_insertion_point(struct:waves_CreateAliasTransactionData) */ +} waves_CreateAliasTransactionData; + +typedef struct _waves_DataTransactionData { + pb_callback_t data; +/* @@protoc_insertion_point(struct:waves_DataTransactionData) */ +} waves_DataTransactionData; + +typedef struct _waves_LeaseCancelTransactionData { + pb_callback_t lease_id; +/* @@protoc_insertion_point(struct:waves_LeaseCancelTransactionData) */ +} waves_LeaseCancelTransactionData; + +typedef struct _waves_SetAssetScriptTransactionData { + pb_callback_t asset_id; + pb_callback_t script; +/* @@protoc_insertion_point(struct:waves_SetAssetScriptTransactionData) */ +} waves_SetAssetScriptTransactionData; + +typedef struct _waves_SetScriptTransactionData { + pb_callback_t script; +/* @@protoc_insertion_point(struct:waves_SetScriptTransactionData) */ +} waves_SetScriptTransactionData; + +typedef struct _waves_UpdateAssetInfoTransactionData { + pb_callback_t asset_id; + pb_callback_t name; + pb_callback_t description; +/* @@protoc_insertion_point(struct:waves_UpdateAssetInfoTransactionData) */ +} waves_UpdateAssetInfoTransactionData; + +typedef PB_BYTES_ARRAY_T(140) waves_Attachment_binary_value_t; +typedef struct _waves_Attachment { + pb_size_t which_attachment; + union { + int64_t int_value; + bool bool_value; + waves_Attachment_binary_value_t binary_value; + char string_value[140]; + } attachment; +/* @@protoc_insertion_point(struct:waves_Attachment) */ +} waves_Attachment; + +typedef struct _waves_BurnTransactionData { + waves_Amount asset_amount; +/* @@protoc_insertion_point(struct:waves_BurnTransactionData) */ +} waves_BurnTransactionData; + +typedef PB_BYTES_ARRAY_T(32767) waves_DataTransactionData_DataEntry_binary_value_t; +typedef struct _waves_DataTransactionData_DataEntry { + pb_callback_t key; + pb_size_t which_value; + union { + int64_t int_value; + bool bool_value; + waves_DataTransactionData_DataEntry_binary_value_t binary_value; + char string_value[32767]; + } value; +/* @@protoc_insertion_point(struct:waves_DataTransactionData_DataEntry) */ +} waves_DataTransactionData_DataEntry; + +typedef struct _waves_ExchangeTransactionData { + int64_t amount; + int64_t price; + int64_t buy_matcher_fee; + int64_t sell_matcher_fee; + pb_callback_t orders; +/* @@protoc_insertion_point(struct:waves_ExchangeTransactionData) */ +} waves_ExchangeTransactionData; + +typedef struct _waves_GenesisTransactionData { + pb_callback_t recipient_address; + int64_t amount; +/* @@protoc_insertion_point(struct:waves_GenesisTransactionData) */ +} waves_GenesisTransactionData; + +typedef struct _waves_InvokeScriptTransactionData { + waves_Recipient d_app; + pb_callback_t function_call; + pb_callback_t payments; +/* @@protoc_insertion_point(struct:waves_InvokeScriptTransactionData) */ +} waves_InvokeScriptTransactionData; + +typedef struct _waves_IssueTransactionData { + pb_callback_t name; + pb_callback_t description; + int64_t amount; + int32_t decimals; + bool reissuable; + pb_callback_t script; +/* @@protoc_insertion_point(struct:waves_IssueTransactionData) */ +} waves_IssueTransactionData; + +typedef struct _waves_LeaseTransactionData { + waves_Recipient recipient; + int64_t amount; +/* @@protoc_insertion_point(struct:waves_LeaseTransactionData) */ +} waves_LeaseTransactionData; + +typedef struct _waves_MassTransferTransactionData_Transfer { + waves_Recipient address; + int64_t amount; +/* @@protoc_insertion_point(struct:waves_MassTransferTransactionData_Transfer) */ +} waves_MassTransferTransactionData_Transfer; + +typedef struct _waves_PaymentTransactionData { + pb_callback_t recipient_address; + int64_t amount; +/* @@protoc_insertion_point(struct:waves_PaymentTransactionData) */ +} waves_PaymentTransactionData; + +typedef struct _waves_ReissueTransactionData { + waves_Amount asset_amount; + bool reissuable; +/* @@protoc_insertion_point(struct:waves_ReissueTransactionData) */ +} waves_ReissueTransactionData; + +typedef struct _waves_SponsorFeeTransactionData { + waves_Amount min_fee; +/* @@protoc_insertion_point(struct:waves_SponsorFeeTransactionData) */ +} waves_SponsorFeeTransactionData; + +typedef struct _waves_MassTransferTransactionData { + pb_callback_t asset_id; + pb_callback_t transfers; + waves_Attachment attachment; +/* @@protoc_insertion_point(struct:waves_MassTransferTransactionData) */ +} waves_MassTransferTransactionData; + +typedef struct _waves_TransferTransactionData { + waves_Recipient recipient; + waves_Amount amount; + waves_Attachment attachment; +/* @@protoc_insertion_point(struct:waves_TransferTransactionData) */ +} waves_TransferTransactionData; + +typedef struct _waves_Transaction { + int32_t chain_id; + pb_callback_t sender_public_key; + waves_Amount fee; + int64_t timestamp; + int32_t version; + pb_size_t which_data; + union { + waves_GenesisTransactionData genesis; + waves_PaymentTransactionData payment; + waves_IssueTransactionData issue; + waves_TransferTransactionData transfer; + waves_ReissueTransactionData reissue; + waves_BurnTransactionData burn; + waves_ExchangeTransactionData exchange; + waves_LeaseTransactionData lease; + waves_LeaseCancelTransactionData lease_cancel; + waves_CreateAliasTransactionData create_alias; + waves_MassTransferTransactionData mass_transfer; + waves_DataTransactionData data_transaction; + waves_SetScriptTransactionData set_script; + waves_SponsorFeeTransactionData sponsor_fee; + waves_SetAssetScriptTransactionData set_asset_script; + waves_InvokeScriptTransactionData invoke_script; + waves_UpdateAssetInfoTransactionData update_asset_info; + } data; +/* @@protoc_insertion_point(struct:waves_Transaction) */ +} waves_Transaction; + +typedef struct _waves_SignedTransaction { + waves_Transaction transaction; + pb_callback_t proofs; +/* @@protoc_insertion_point(struct:waves_SignedTransaction) */ +} waves_SignedTransaction; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define waves_SignedTransaction_init_default {waves_Transaction_init_default, {{NULL}, NULL}} +#define waves_Transaction_init_default {0, {{NULL}, NULL}, waves_Amount_init_default, 0, 0, 0, {waves_GenesisTransactionData_init_default}} +#define waves_GenesisTransactionData_init_default {{{NULL}, NULL}, 0} +#define waves_PaymentTransactionData_init_default {{{NULL}, NULL}, 0} +#define waves_Attachment_init_default {0, {0}} +#define waves_TransferTransactionData_init_default {waves_Recipient_init_default, waves_Amount_init_default, waves_Attachment_init_default} +#define waves_CreateAliasTransactionData_init_default {{{NULL}, NULL}} +#define waves_DataTransactionData_init_default {{{NULL}, NULL}} +#define waves_DataTransactionData_DataEntry_init_default {{{NULL}, NULL}, 0, {0}} +#define waves_MassTransferTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, waves_Attachment_init_default} +#define waves_MassTransferTransactionData_Transfer_init_default {waves_Recipient_init_default, 0} +#define waves_LeaseTransactionData_init_default {waves_Recipient_init_default, 0} +#define waves_LeaseCancelTransactionData_init_default {{{NULL}, NULL}} +#define waves_BurnTransactionData_init_default {waves_Amount_init_default} +#define waves_IssueTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} +#define waves_ReissueTransactionData_init_default {waves_Amount_init_default, 0} +#define waves_SetAssetScriptTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_SetScriptTransactionData_init_default {{{NULL}, NULL}} +#define waves_ExchangeTransactionData_init_default {0, 0, 0, 0, {{NULL}, NULL}} +#define waves_SponsorFeeTransactionData_init_default {waves_Amount_init_default} +#define waves_InvokeScriptTransactionData_init_default {waves_Recipient_init_default, {{NULL}, NULL}, {{NULL}, NULL}} +#define waves_UpdateAssetInfoTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} +#define waves_SignedTransaction_init_zero {waves_Transaction_init_zero, {{NULL}, NULL}} +#define waves_Transaction_init_zero {0, {{NULL}, NULL}, waves_Amount_init_zero, 0, 0, 0, {waves_GenesisTransactionData_init_zero}} +#define waves_GenesisTransactionData_init_zero {{{NULL}, NULL}, 0} +#define waves_PaymentTransactionData_init_zero {{{NULL}, NULL}, 0} +#define waves_Attachment_init_zero {0, {0}} +#define waves_TransferTransactionData_init_zero {waves_Recipient_init_zero, waves_Amount_init_zero, waves_Attachment_init_zero} +#define waves_CreateAliasTransactionData_init_zero {{{NULL}, NULL}} +#define waves_DataTransactionData_init_zero {{{NULL}, NULL}} +#define waves_DataTransactionData_DataEntry_init_zero {{{NULL}, NULL}, 0, {0}} +#define waves_MassTransferTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, waves_Attachment_init_zero} +#define waves_MassTransferTransactionData_Transfer_init_zero {waves_Recipient_init_zero, 0} +#define waves_LeaseTransactionData_init_zero {waves_Recipient_init_zero, 0} +#define waves_LeaseCancelTransactionData_init_zero {{{NULL}, NULL}} +#define waves_BurnTransactionData_init_zero {waves_Amount_init_zero} +#define waves_IssueTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} +#define waves_ReissueTransactionData_init_zero {waves_Amount_init_zero, 0} +#define waves_SetAssetScriptTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_SetScriptTransactionData_init_zero {{{NULL}, NULL}} +#define waves_ExchangeTransactionData_init_zero {0, 0, 0, 0, {{NULL}, NULL}} +#define waves_SponsorFeeTransactionData_init_zero {waves_Amount_init_zero} +#define waves_InvokeScriptTransactionData_init_zero {waves_Recipient_init_zero, {{NULL}, NULL}, {{NULL}, NULL}} +#define waves_UpdateAssetInfoTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} + +/* Field tags (for use in manual encoding/decoding) */ +#define waves_CreateAliasTransactionData_alias_tag 1 +#define waves_DataTransactionData_data_tag 1 +#define waves_LeaseCancelTransactionData_lease_id_tag 1 +#define waves_SetAssetScriptTransactionData_asset_id_tag 1 +#define waves_SetAssetScriptTransactionData_script_tag 2 +#define waves_SetScriptTransactionData_script_tag 1 +#define waves_UpdateAssetInfoTransactionData_asset_id_tag 1 +#define waves_UpdateAssetInfoTransactionData_name_tag 2 +#define waves_UpdateAssetInfoTransactionData_description_tag 3 +#define waves_Attachment_int_value_tag 1 +#define waves_Attachment_bool_value_tag 2 +#define waves_Attachment_binary_value_tag 3 +#define waves_Attachment_string_value_tag 4 +#define waves_BurnTransactionData_asset_amount_tag 1 +#define waves_DataTransactionData_DataEntry_int_value_tag 10 +#define waves_DataTransactionData_DataEntry_bool_value_tag 11 +#define waves_DataTransactionData_DataEntry_binary_value_tag 12 +#define waves_DataTransactionData_DataEntry_string_value_tag 13 +#define waves_DataTransactionData_DataEntry_key_tag 1 +#define waves_ExchangeTransactionData_amount_tag 1 +#define waves_ExchangeTransactionData_price_tag 2 +#define waves_ExchangeTransactionData_buy_matcher_fee_tag 3 +#define waves_ExchangeTransactionData_sell_matcher_fee_tag 4 +#define waves_ExchangeTransactionData_orders_tag 5 +#define waves_GenesisTransactionData_recipient_address_tag 1 +#define waves_GenesisTransactionData_amount_tag 2 +#define waves_InvokeScriptTransactionData_d_app_tag 1 +#define waves_InvokeScriptTransactionData_function_call_tag 2 +#define waves_InvokeScriptTransactionData_payments_tag 3 +#define waves_IssueTransactionData_name_tag 1 +#define waves_IssueTransactionData_description_tag 2 +#define waves_IssueTransactionData_amount_tag 3 +#define waves_IssueTransactionData_decimals_tag 4 +#define waves_IssueTransactionData_reissuable_tag 5 +#define waves_IssueTransactionData_script_tag 6 +#define waves_LeaseTransactionData_recipient_tag 1 +#define waves_LeaseTransactionData_amount_tag 2 +#define waves_MassTransferTransactionData_Transfer_address_tag 1 +#define waves_MassTransferTransactionData_Transfer_amount_tag 2 +#define waves_PaymentTransactionData_recipient_address_tag 1 +#define waves_PaymentTransactionData_amount_tag 2 +#define waves_ReissueTransactionData_asset_amount_tag 1 +#define waves_ReissueTransactionData_reissuable_tag 2 +#define waves_SponsorFeeTransactionData_min_fee_tag 1 +#define waves_MassTransferTransactionData_asset_id_tag 1 +#define waves_MassTransferTransactionData_transfers_tag 2 +#define waves_MassTransferTransactionData_attachment_tag 3 +#define waves_TransferTransactionData_recipient_tag 1 +#define waves_TransferTransactionData_amount_tag 2 +#define waves_TransferTransactionData_attachment_tag 3 +#define waves_Transaction_genesis_tag 101 +#define waves_Transaction_payment_tag 102 +#define waves_Transaction_issue_tag 103 +#define waves_Transaction_transfer_tag 104 +#define waves_Transaction_reissue_tag 105 +#define waves_Transaction_burn_tag 106 +#define waves_Transaction_exchange_tag 107 +#define waves_Transaction_lease_tag 108 +#define waves_Transaction_lease_cancel_tag 109 +#define waves_Transaction_create_alias_tag 110 +#define waves_Transaction_mass_transfer_tag 111 +#define waves_Transaction_data_transaction_tag 112 +#define waves_Transaction_set_script_tag 113 +#define waves_Transaction_sponsor_fee_tag 114 +#define waves_Transaction_set_asset_script_tag 115 +#define waves_Transaction_invoke_script_tag 116 +#define waves_Transaction_update_asset_info_tag 117 +#define waves_Transaction_chain_id_tag 1 +#define waves_Transaction_sender_public_key_tag 2 +#define waves_Transaction_fee_tag 3 +#define waves_Transaction_timestamp_tag 4 +#define waves_Transaction_version_tag 5 +#define waves_SignedTransaction_transaction_tag 1 +#define waves_SignedTransaction_proofs_tag 2 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t waves_SignedTransaction_fields[3]; +extern const pb_field_t waves_Transaction_fields[23]; +extern const pb_field_t waves_GenesisTransactionData_fields[3]; +extern const pb_field_t waves_PaymentTransactionData_fields[3]; +extern const pb_field_t waves_Attachment_fields[5]; +extern const pb_field_t waves_TransferTransactionData_fields[4]; +extern const pb_field_t waves_CreateAliasTransactionData_fields[2]; +extern const pb_field_t waves_DataTransactionData_fields[2]; +extern const pb_field_t waves_DataTransactionData_DataEntry_fields[6]; +extern const pb_field_t waves_MassTransferTransactionData_fields[4]; +extern const pb_field_t waves_MassTransferTransactionData_Transfer_fields[3]; +extern const pb_field_t waves_LeaseTransactionData_fields[3]; +extern const pb_field_t waves_LeaseCancelTransactionData_fields[2]; +extern const pb_field_t waves_BurnTransactionData_fields[2]; +extern const pb_field_t waves_IssueTransactionData_fields[7]; +extern const pb_field_t waves_ReissueTransactionData_fields[3]; +extern const pb_field_t waves_SetAssetScriptTransactionData_fields[3]; +extern const pb_field_t waves_SetScriptTransactionData_fields[2]; +extern const pb_field_t waves_ExchangeTransactionData_fields[6]; +extern const pb_field_t waves_SponsorFeeTransactionData_fields[2]; +extern const pb_field_t waves_InvokeScriptTransactionData_fields[4]; +extern const pb_field_t waves_UpdateAssetInfoTransactionData_fields[4]; + +/* Maximum encoded size of messages (where known) */ +/* waves_SignedTransaction_size depends on runtime parameters */ +/* waves_Transaction_size depends on runtime parameters */ +/* waves_GenesisTransactionData_size depends on runtime parameters */ +/* waves_PaymentTransactionData_size depends on runtime parameters */ +#define waves_Attachment_size 143 +#define waves_TransferTransactionData_size (190 + waves_Amount_size) +/* waves_CreateAliasTransactionData_size depends on runtime parameters */ +/* waves_DataTransactionData_size depends on runtime parameters */ +/* waves_DataTransactionData_DataEntry_size depends on runtime parameters */ +/* waves_MassTransferTransactionData_size depends on runtime parameters */ +#define waves_MassTransferTransactionData_Transfer_size 49 +#define waves_LeaseTransactionData_size 49 +/* waves_LeaseCancelTransactionData_size depends on runtime parameters */ +#define waves_BurnTransactionData_size (6 + waves_Amount_size) +/* waves_IssueTransactionData_size depends on runtime parameters */ +#define waves_ReissueTransactionData_size (8 + waves_Amount_size) +/* waves_SetAssetScriptTransactionData_size depends on runtime parameters */ +/* waves_SetScriptTransactionData_size depends on runtime parameters */ +/* waves_ExchangeTransactionData_size depends on runtime parameters */ +#define waves_SponsorFeeTransactionData_size (6 + waves_Amount_size) +/* waves_InvokeScriptTransactionData_size depends on runtime parameters */ +/* waves_UpdateAssetInfoTransactionData_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define TRANSACTION_MESSAGES \ + + +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/src/ui/nanopb/simple.pb.c b/src/ui/nanopb/simple.pb.c deleted file mode 100644 index b92dc4c7..00000000 --- a/src/ui/nanopb/simple.pb.c +++ /dev/null @@ -1,19 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.3 at Tue Apr 7 15:35:57 2020. */ - -#include "simple.pb.h" - -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 -#error Regenerate this file with the current version of nanopb generator. -#endif - - - -const pb_field_t SimpleMessage_fields[2] = { - PB_FIELD( 1, INT32 , REQUIRED, STATIC , FIRST, SimpleMessage, lucky_number, lucky_number, 0), - PB_LAST_FIELD -}; - - -/* @@protoc_insertion_point(eof) */ diff --git a/src/ui/nanopb/simple.proto b/src/ui/nanopb/simple.proto deleted file mode 100644 index 5c73a3b2..00000000 --- a/src/ui/nanopb/simple.proto +++ /dev/null @@ -1,9 +0,0 @@ -// A very simple protocol definition, consisting of only -// one message. - -syntax = "proto2"; - -message SimpleMessage { - required int32 lucky_number = 1; -} - diff --git a/src/ui/ui.c b/src/ui/ui.c index de9fdb6a..bb2046b6 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -24,9 +24,6 @@ #include "../main.h" #include "../crypto/waves.h" #include "transactions/transfer.h" -#include "nanopb/pb_encode.h" -#include "nanopb/pb_decode.h" -#include "nanopb/simple.pb.h" #ifdef TARGET_BLUE #include "blue/ui_menus_blue.h" @@ -177,65 +174,6 @@ void make_allowed_ui_steps(bool is_last) { build_other_data_ui(); } PRINTF("make_allowed_ui_steps end\n"); - // Testing simpe protobuf - /* This is the buffer where we will store our message. */ - PRINTF("init variables\n"); - uint8_t buffer[128]; - size_t message_length; - bool status; - - /* Encode our message */ - { - /* Allocate space on the stack to store the message data. - * - * Nanopb generates simple struct definitions for all the messages. - * - check out the contents of simple.pb.h! - * It is a good idea to always initialize your structures - * so that you do not have garbage data from RAM in there. - */ - SimpleMessage message = SimpleMessage_init_zero; - /* Create a stream that will write to our buffer. */ - pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); - /* Fill in the lucky number */ - message.lucky_number = 13; - /* Now we are ready to encode the message! */ - status = pb_encode(&stream, SimpleMessage_fields, &message); - message_length = stream.bytes_written; - - /* Then just check for any errors.. */ - if (!status) { - PRINTF("Encoding failed: %s\n", PB_GET_ERROR(&stream)); - return; - } - } - - /* Now we could transmit the message over network, store it in a file or - * wrap it to a pigeon's leg. - */ - - /* But because we are lazy, we will just decode it immediately. */ - - { - PRINTF("init message\n"); - /* Allocate space for the decoded message. */ - SimpleMessage message = SimpleMessage_init_zero; - PRINTF("create stream\n"); - /* Create a stream that reads from the buffer. */ - pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); - PRINTF("decode message\n"); - /* Now we are ready to decode the message. */ - status = pb_decode(&stream, SimpleMessage_fields, &message); - - /* Check for errors... */ - if (!status) - { - PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); - return ; - } - - /* Print the data contained in the message. */ - PRINTF("Your lucky number was %d!\n", (int)message.lucky_number); - } } // Show the transaction details for the user to approve From 884af75ad837728f0565d08323f961feb253dbb8 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Tue, 21 Apr 2020 18:35:16 +0400 Subject: [PATCH 06/26] add new tx bytes --- python/ledger-waves.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index 96cb5de8..944031af 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -243,6 +243,12 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', trx = Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) return trx.SerializeToString() +build_transfer_protobuf('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, + 'privet', timestamp = 1526477921829) + + while (True): while (dongle == None): try: @@ -385,7 +391,7 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, 'privet', timestamp = 1526477921829) #some_transfer_bytes = b"0aa40108571220b985d724da1564a6354040b1718b8c8e8c59533a20b71ba3c64d5dfe7f379f381a270a200080800142003a8024017fef3519e54affbcae5c01347f648064019b0081c92c10d2b9ea0a20f398cdf7b3ca8fd03e2802c206480a160a1496639366f56efd312248d1edf056070fd5b8941c122a0a204a83e780ff016100147f073b2580ff80ffb9eba30087f400cdb2dc3b5d017c4e1099eebaf4c6b2121a021a00121100d716230100d88280edcdc30ce97f64ed122001807701fd7f01d37fb87f88ffbe01c0ff01ff010005afffcb7fb201a0f4b974122c8c8000ff0a7fff8015381f807801c1007f7f01d700c521ff018dc700017f80807680097f39378e01b500804f122980099e8b80ffff00ad2500870080017f7f880b2ca72e7fff175a00f0da00ff00803dbd2bff8000995c" - + some_transfer_bytes = base58.b58decode("uq4YDsWuUhQ2ajpzvHxWeikWkF8XodVWi8F1VdYsqFESLGc2k6g5UvtxVrER4a") input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: From e12d0f7129562d6a8a0422e67089afc85cf0e17b Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Wed, 17 Jun 2020 18:07:03 +0400 Subject: [PATCH 07/26] add protobuf support --- Makefile | 7 +- python/ledger-waves.py | 470 +++- python/nanopb_pb2.py | 467 ++++ python/recipient_pb2.py | 16 +- python/transaction_pb2.py | 184 +- src/crypto/stream_eddsa_sign.c | 6 +- src/crypto/stream_eddsa_sign.h | 1 - src/crypto/waves.c | 18 +- src/crypto/waves.h | 5 +- src/main.c | 174 +- src/main.h | 68 +- src/nanopb/pb.h | 1014 +++++--- src/nanopb/pb_common.c | 334 ++- src/nanopb/pb_common.h | 24 +- src/nanopb/pb_custom.c | 241 +- src/nanopb/pb_custom.h | 30 +- src/nanopb/pb_decode.c | 2575 +++++++++++---------- src/nanopb/pb_decode.h | 133 +- src/nanopb/pb_encode.c | 1396 +++++------ src/nanopb/pb_encode.h | 93 +- src/nanopb_stubs/amount.pb.c | 17 +- src/nanopb_stubs/amount.pb.h | 42 +- src/nanopb_stubs/order.pb.c | 58 +- src/nanopb_stubs/order.pb.h | 139 +- src/nanopb_stubs/recipient.pb.c | 17 +- src/nanopb_stubs/recipient.pb.h | 61 +- src/nanopb_stubs/transaction.pb.c | 225 +- src/nanopb_stubs/transaction.pb.h | 753 +++--- src/ui/blue/ui_menus_blue.h | 3558 ++++++++++++++++++++++++++++- src/ui/nanox/ui_menus_nanox.h | 790 ++++++- src/ui/print_amount.c | 64 + src/ui/print_amount.h | 44 +- src/ui/transactions/protobuf.c | 271 +++ src/ui/transactions/protobuf.h | 34 + src/ui/transactions/transfer.c | 166 +- src/ui/ui.c | 228 +- src/ui/ui.h | 1 + 37 files changed, 9861 insertions(+), 3863 deletions(-) create mode 100644 python/nanopb_pb2.py create mode 100644 src/ui/print_amount.c create mode 100644 src/ui/transactions/protobuf.c create mode 100644 src/ui/transactions/protobuf.h diff --git a/Makefile b/Makefile index 996675c4..5fe407f7 100755 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ include $(BOLOS_SDK)/Makefile.defines # Main app configuration APPVERSION_M=1 -APPVERSION_N=1 +APPVERSION_N=2 APPVERSION_P=0 APPNAME = "Waves" @@ -81,7 +81,6 @@ DEFINES += MAX_DATA_SIZE=128 DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" - ifeq ($(TARGET_NAME),TARGET_NANOX) DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 @@ -98,7 +97,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 1 +DEBUG = 0 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) @@ -106,7 +105,6 @@ ifneq ($(DEBUG),0) DEFINES += HAVE_PRINTF_PB PRINTF_PB=mcu_usb_printf else DEFINES += HAVE_PRINTF PRINTF=screen_printf - DEFINES += HAVE_PRINTF_PB PRINTF_PB=screen_printf endif else DEFINES += PRINTF\(...\)= @@ -158,6 +156,5 @@ include $(BOLOS_SDK)/Makefile.glyphs include $(BOLOS_SDK)/Makefile.rules - listvariants: @echo VARIANTS COIN waves diff --git a/python/ledger-waves.py b/python/ledger-waves.py index 944031af..981de042 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -24,8 +24,10 @@ import pywaves as pw import time import binascii +import base64 from amount_pb2 import Amount -from transaction_pb2 import Transaction, TransferTransactionData, Attachment +import transaction_pb2 as tpb +#from transaction_pb2 import Transaction, TransferTransactionData, DataTransactionData, IssueTransactionData, ReissueTransactionData, BurnTransactionData, LeaseTransactionData Attachment from recipient_pb2 import Recipient global dongle @@ -232,22 +234,139 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee return sData -def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 2): +def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + to = Recipient(public_key_hash=base58.b58decode(recipient)) + amountTx= Amount(asset_id=(base58.b58decode(asset.assetId) if asset else b'\0'), amount=amount) + transfer = tpb.TransferTransactionData(recipient=to, amount=amountTx, attachment=attachment) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) + return trx.SerializeToString() + +def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + to = Recipient(public_key_hash=base58.b58decode(recipient)) + transfers = list() + transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) + transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) + transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) + mass_transfer = tpb.MassTransferTransactionData(asset_id=(base58.b58decode(asset.assetId) if asset else b'\0'), transfers = transfers, attachment=attachment) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, mass_transfer=mass_transfer) + return trx.SerializeToString() + +def build_issue_protobuf(publicKey, name, descr, amount, decimals, reissue, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + issue = tpb.IssueTransactionData(name = name, description = descr, amount=amount, decimals=decimals, reissuable = reissue) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, issue=issue) + return trx.SerializeToString() + +def build_set_ac_script_protobuf(publicKey, script, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + scr = tpb.SetScriptTransactionData(script=script) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, set_script=scr) + return trx.SerializeToString() + +def build_set_as_script_protobuf(publicKey, asset, script, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + scr = tpb.SetAssetScriptTransactionData(asset_id=base58.b58decode(asset.assetId), script=script) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, set_asset_script=scr) + return trx.SerializeToString() + +def build_reissue_protobuf(publicKey, asset, amount, re, feeAsset='', txFee=100000, timestamp=0, version = 3): if timestamp == 0: timestamp = int(time.time() * 1000) - msg = Attachment(string_value = attachment) - to = Recipient(public_key_hash=base58.b58decode(recipient.address)) amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) - transfer = TransferTransactionData(recipient=to, amount=amountTx, attachment=msg) + reissue = tpb.ReissueTransactionData(asset_amount=amountTx, reissuable = re) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, reissue=reissue) + return trx.SerializeToString() + +def build_burn_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + burn = tpb.BurnTransactionData(asset_amount=amountTx) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, burn=burn) + return trx.SerializeToString() + +def build_lease_protobuf(publicKey, to, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + recipient = Recipient(public_key_hash=base58.b58decode(to)) + lease = tpb.LeaseTransactionData(recipient=recipient, amount=amount) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, lease=lease) + return trx.SerializeToString() + +def build_cancel_lease_protobuf(publicKey, leaseId, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + lease_cancel = tpb.LeaseCancelTransactionData(lease_id = base58.b58decode(leaseId)) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, lease_cancel=lease_cancel) + return trx.SerializeToString() + +def build_creating_alias_protobuf(publicKey, alias, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + alias = tpb.CreateAliasTransactionData(alias = alias) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, create_alias=alias) + return trx.SerializeToString() + +def build_update_asset_protobuf(publicKey, asset, name, description, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + update_asset = tpb.UpdateAssetInfoTransactionData(asset_id = base58.b58decode(asset.assetId), name=name, description=description) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, update_asset_info=update_asset) + return trx.SerializeToString() + +def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + list = [] + for x in range(3): + k = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) + s = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) + dataEntery = tpb.DataTransactionData.DataEntry(key=k, string_value=s ) + list.append(dataEntery) + data = tpb.DataTransactionData(data = list) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b''), amount=txFee) - trx = Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) + trx = tpb.Transaction(chain_id=84, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, data_transaction=data) return trx.SerializeToString() -build_transfer_protobuf('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', - pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, - 'privet', timestamp = 1526477921829) - +def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + amountTx= Amount(asset_id=(base58.b58decode(asset.assetId) if feeAsset else b'\0'), amount=amount) + sponsorship = tpb.SponsorFeeTransactionData(min_fee=amountTx) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, sponsor_fee=sponsorship) + return trx.SerializeToString() + +def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + amounts = [] + amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + amounts.append(amountTx) + amounts.append(amountTx) + to = Recipient(public_key_hash=base58.b58decode(dapp)) + invoke = tpb.InvokeScriptTransactionData(d_app = to, function_call = function, payments = amounts) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, invoke_script=invoke) + return trx.SerializeToString() while (True): while (dongle == None): @@ -293,7 +412,6 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', binary_data += chr(8) # fee amount asset decimals binary_data += chr(8) - # Tx info # # amount: 1 @@ -305,23 +423,24 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', # fee asset: WAVES some_transfer_bytes = build_transfer_bytes('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000000, 'privet', timestamp = 1526477921829) input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: # 2 first bytes aren't the tx data, but info type for the ledger - print(len(some_transfer_bytes)) binary_data += b'\4\2' binary_data += struct.pack(">I", len(some_transfer_bytes)) binary_data += some_transfer_bytes binary_data += some_transfer_bytes + binary_data += some_transfer_bytes print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) else: binary_input = base58.b58decode(input) binary_data += struct.pack(">I", len(binary_input)) binary_data += binary_input binary_data += binary_input + binary_data += binary_input print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) signature = None @@ -365,86 +484,249 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', version = getVersionFromDongle() print('App version is {}.{}.{}'.format(version[0],version[1],version[2])) elif (select == "4"): - path = raw_input( - colors.fg.lightblue + "Please input BIP-32 path (for example \"44'/5741564'/0'/0'/1'\")> " + colors.reset) - if len(path) == 0: - path = "44'/5741564'/0'/0'/1'" - binary_data = path_to_bytes(expand_path(path)) - print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) - - # tx amount asset decimals - binary_data += chr(8) - # fee amount asset decimals - binary_data += chr(8) - - # Tx info - # - # amount: 1 - # asset: 9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t - # from: 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - # to: 3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK - # attachment: privet - # fee: 0.001 - # fee asset: WAVES - some_transfer_bytes = build_transfer_protobuf('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', - pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1, - 'privet', timestamp = 1526477921829) - #some_transfer_bytes = b"0aa40108571220b985d724da1564a6354040b1718b8c8e8c59533a20b71ba3c64d5dfe7f379f381a270a200080800142003a8024017fef3519e54affbcae5c01347f648064019b0081c92c10d2b9ea0a20f398cdf7b3ca8fd03e2802c206480a160a1496639366f56efd312248d1edf056070fd5b8941c122a0a204a83e780ff016100147f073b2580ff80ffb9eba30087f400cdb2dc3b5d017c4e1099eebaf4c6b2121a021a00121100d716230100d88280edcdc30ce97f64ed122001807701fd7f01d37fb87f88ffbe01c0ff01ff010005afffcb7fb201a0f4b974122c8c8000ff0a7fff8015381f807801c1007f7f01d700c521ff018dc700017f80807680097f39378e01b500804f122980099e8b80ffff00ad2500870080017f7f880b2ca72e7fff175a00f0da00ff00803dbd2bff8000995c" - some_transfer_bytes = base58.b58decode("uq4YDsWuUhQ2ajpzvHxWeikWkF8XodVWi8F1VdYsqFESLGc2k6g5UvtxVrER4a") - input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( - str(some_transfer_bytes)) + "\")> " + colors.reset) - if len(input) == 0: - # 2 first bytes aren't the tx data, but info type for the ledger - binary_data += b'\4\2' - binary_data += struct.pack(">I", len(some_transfer_bytes)) - binary_data += some_transfer_bytes - binary_data += some_transfer_bytes - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) - else: - binary_input = base58.b58decode(input) - binary_data += struct.pack(">I", len(binary_input)) - binary_data += binary_input - binary_data += binary_input - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) - print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) - signature = None while (True): - try: - offset = 0 - while offset != len(binary_data): - if (len(binary_data) - offset) > CHUNK_SIZE: - chunk = binary_data[offset: offset + CHUNK_SIZE] - else: - chunk = binary_data[offset:] - if (offset + len(chunk)) == len(binary_data): - p1 = 0x80 - else: - p1 = 0x00 - - if (offset == 0): - print("Waiting for approval to sign on the Ledger Nano S") - - apdu = bytes("8002".decode('hex')) + chr(p1) + chain_id + chr(len(chunk)) + bytes(chunk) - signature = dongle.exchange(apdu) - offset += len(chunk) - - print("signature " + base58.b58encode(str(signature))) - break - except CommException as e: - if (e.sw == 0x6990): - print(colors.fg.red + "Transaction buffer max size reached." + colors.reset) - if (e.sw == 0x6985): - print(colors.fg.red + "Required condition failed." + colors.reset) - if (e.sw == 0x9100): - print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) - break - except Exception as e: - print(e, type(e)) - answer = raw_input( - "Please connect your Ledger Nano S, unlock, and launch the Waves app. Press when ready. (Q quits)") - if (answer.upper() == 'Q'): - sys.exit(0) - sys.exc_clear() + print("") + print(colors.fg.lightcyan + colors.bold + "Ledger Nano S - Waves test app" + colors.reset) + print(colors.fg.lightcyan + colors.bold + "Test protobuf transactions" + colors.reset) + print(colors.fg.white + "\t 3. Issue" + colors.reset) + print(colors.fg.white + "\t 4. Transfer" + colors.reset) + print(colors.fg.white + "\t 5. Reissue" + colors.reset) + print(colors.fg.white + "\t 6. Burn" + colors.reset) + print(colors.fg.white + "\t 7. Exchange" + colors.reset) + print(colors.fg.white + "\t 8. Lease" + colors.reset) + print(colors.fg.white + "\t 9. Lease Cancel" + colors.reset) + print(colors.fg.white + "\t 10. Create Alias" + colors.reset) + print(colors.fg.white + "\t 11. MassTransfer" + colors.reset) + print(colors.fg.white + "\t 12. Data" + colors.reset) + print(colors.fg.white + "\t 13. Set Account Script" + colors.reset) + print(colors.fg.white + "\t 14. Sponsor Fee" + colors.reset) + print(colors.fg.white + "\t 15. Set Asset Script" + colors.reset) + print(colors.fg.white + "\t 16. Invoke Script" + colors.reset) + print(colors.fg.white + "\t 17. Update Asset Info" + colors.reset) + print(colors.fg.white + "\t 0. Exit" + colors.reset) + select = raw_input(colors.fg.cyan + "Please select transaction type> " + colors.reset) + decimals = 8 # tx amount asset decimals + feeDecimals = 8 #fee amount asset decimals + if (select == "3"): + decimals = 3 + some_transfer_bytes = build_issue_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "Test asset name", + "Test asset description, Test asset description, Test asset description", + 1000000000, + decimals, + True, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "4"): + decimals = 8 + some_transfer_bytes = build_transfer_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), + 100000000, + 'privet', + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "5"): + decimals = 8 + some_transfer_bytes = build_reissue_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), + 100000000, + True, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "6"): + decimals = 8 + some_transfer_bytes = build_burn_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), + 1000000000, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + #elif (select == "7"): + + elif (select == "8"): + some_transfer_bytes = build_lease_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + 100000000000, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "9"): + some_transfer_bytes = build_cancel_lease_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + 'B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu', + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "10"): + some_transfer_bytes = build_creating_alias_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "Test Alias", + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "11"): + some_transfer_bytes = build_masstransfer_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL, + pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), + 10000000, + 'privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000', + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "12"): + some_transfer_bytes = build_data_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "13"): + script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") + some_transfer_bytes = build_set_ac_script_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + script, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "14"): + decimals = 6 + some_transfer_bytes = build_sponsorship_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + 10000, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif (select == "15"): + script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") + some_transfer_bytes = build_set_as_script_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + script, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + #elif (select == "16"): + #fname = "function_name" + #function_call = "" + #fcal=chr(1) + chr(9) + chr(1) + fname.encode() + function_call.encode() + + elif (select == "17"): + some_transfer_bytes = build_update_asset_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + "Test name 1", + "Test descr", + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + else: + break; + + path = raw_input(colors.fg.lightblue + "Please input BIP-32 path (for example \"44'/5741564'/0'/0'/1'\")> " + colors.reset) + if len(path) == 0: + path = "44'/5741564'/0'/0'/1'" + binary_data = path_to_bytes(expand_path(path)) + print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) + + # tx amount asset decimals + binary_data += chr(decimals) + # fee amount asset decimals + binary_data += chr(feeDecimals) + + #some_transfer_bytes = base58.b58decode("uq4YDsWuUhQ2ajpzvHxWeikWkF8XodVWi8F1VdYsqFESLGc2k6g5UvtxVrER4a") + #some_transfer_bytes = base58.b58decode("c4wP1kugNdzm3Sm88YVaJ3dVZ73S1RshSZNxvqmCZbQUW5yDSCGuXVK666EwipM4yqoA7EeDzseLjSDRQFaoG7pcGvSMrHEqVxw8z3qoBb3zjEvpMhFG598koLXBTZS8RXvN4U4LLJpUcEnqAbDrM4jeUwcYkqekMM3Mbm8tWAaTUbwHgE4DbUPoUid3xncWovvcZ5j9RBExrKpNhxmN1YDS2mwK59GnN4KxUxMnwAuQ5dgrbkAnDGCV9TjeJemj6eCLHKr6mhGUns7W69fRioUmJMADbkYTvgJe1nFgG5n8GiavNfDeCNKD8CYjwZBgZtRZma88pcfAtgBG293JTgcBgSdJWAMTT5J4B5URhrJWyF3mNdq6rbumTGWTGpA8HgYEPA2VgD6EGRprm1DYwdr8UD7HEx2gzDTV6A31") + input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( + str(some_transfer_bytes)) + "\")> " + colors.reset) + if len(input) == 0: + # 2 first bytes aren't the tx data, but info type for the ledger + binary_data += chr(int(select)) + chr(3) + binary_data += struct.pack(">I", len(some_transfer_bytes)) + binary_data += some_transfer_bytes + binary_data += some_transfer_bytes + binary_data += some_transfer_bytes + print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) + else: + binary_input = base58.b58decode(input) + binary_data += struct.pack(">I", len(binary_input)) + binary_data += binary_input + binary_data += binary_input + binary_data += binary_input + print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) + print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) + + signature = None + while (True): + try: + offset = 0 + while offset != len(binary_data): + if (len(binary_data) - offset) > CHUNK_SIZE: + chunk = binary_data[offset: offset + CHUNK_SIZE] + else: + chunk = binary_data[offset:] + if (offset + len(chunk)) == len(binary_data): + p1 = 0x80 + else: + p1 = 0x00 + + if (offset == 0): + print("Waiting for approval to sign on the Ledger Nano S") + + apdu = bytes("8002".decode('hex')) + chr(p1) + chain_id + chr(len(chunk)) + bytes(chunk) + signature = dongle.exchange(apdu) + offset += len(chunk) + + print("signature " + base58.b58encode(str(signature))) + break + except CommException as e: + if (e.sw == 0x6990): + print(colors.fg.red + "Transaction buffer max size reached." + colors.reset) + if (e.sw == 0x6985): + print(colors.fg.red + "Required condition failed." + colors.reset) + if (e.sw == 0x9100): + print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + break + except Exception as e: + print(e, type(e)) + answer = raw_input( + "Please connect your Ledger Nano S, unlock, and launch the Waves app. Press when ready. (Q quits)") + if (answer.upper() == 'Q'): + sys.exit(0) + sys.exc_clear() else: break diff --git a/python/nanopb_pb2.py b/python/nanopb_pb2.py new file mode 100644 index 00000000..2d7f0be9 --- /dev/null +++ b/python/nanopb_pb2.py @@ -0,0 +1,467 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: nanopb.proto + +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='nanopb.proto', + package='', + syntax='proto2', + serialized_options=b'\n\030fi.kapsi.koti.jpa.nanopb', + serialized_pb=b'\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xd9\x06\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb' + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + +_FIELDTYPE = _descriptor.EnumDescriptor( + name='FieldType', + full_name='FieldType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FT_DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_CALLBACK', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_POINTER', index=2, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_STATIC', index=3, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_IGNORE', index=4, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_INLINE', index=5, number=5, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=910, + serialized_end=1015, +) +_sym_db.RegisterEnumDescriptor(_FIELDTYPE) + +FieldType = enum_type_wrapper.EnumTypeWrapper(_FIELDTYPE) +_INTSIZE = _descriptor.EnumDescriptor( + name='IntSize', + full_name='IntSize', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IS_DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_8', index=1, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_16', index=2, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_32', index=3, number=32, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_64', index=4, number=64, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1017, + serialized_end=1085, +) +_sym_db.RegisterEnumDescriptor(_INTSIZE) + +IntSize = enum_type_wrapper.EnumTypeWrapper(_INTSIZE) +_TYPENAMEMANGLING = _descriptor.EnumDescriptor( + name='TypenameMangling', + full_name='TypenameMangling', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='M_NONE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_STRIP_PACKAGE', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_FLATTEN', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_PACKAGE_INITIALS', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1087, + serialized_end=1177, +) +_sym_db.RegisterEnumDescriptor(_TYPENAMEMANGLING) + +TypenameMangling = enum_type_wrapper.EnumTypeWrapper(_TYPENAMEMANGLING) +_DESCRIPTORSIZE = _descriptor.EnumDescriptor( + name='DescriptorSize', + full_name='DescriptorSize', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DS_AUTO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_1', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_2', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_4', index=3, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_8', index=4, number=8, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1179, + serialized_end=1248, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORSIZE) + +DescriptorSize = enum_type_wrapper.EnumTypeWrapper(_DESCRIPTORSIZE) +FT_DEFAULT = 0 +FT_CALLBACK = 1 +FT_POINTER = 4 +FT_STATIC = 2 +FT_IGNORE = 3 +FT_INLINE = 5 +IS_DEFAULT = 0 +IS_8 = 8 +IS_16 = 16 +IS_32 = 32 +IS_64 = 64 +M_NONE = 0 +M_STRIP_PACKAGE = 1 +M_FLATTEN = 2 +M_PACKAGE_INITIALS = 3 +DS_AUTO = 0 +DS_1 = 1 +DS_2 = 2 +DS_4 = 4 +DS_8 = 8 + +NANOPB_FILEOPT_FIELD_NUMBER = 1010 +nanopb_fileopt = _descriptor.FieldDescriptor( + name='nanopb_fileopt', full_name='nanopb_fileopt', index=0, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_MSGOPT_FIELD_NUMBER = 1010 +nanopb_msgopt = _descriptor.FieldDescriptor( + name='nanopb_msgopt', full_name='nanopb_msgopt', index=1, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_ENUMOPT_FIELD_NUMBER = 1010 +nanopb_enumopt = _descriptor.FieldDescriptor( + name='nanopb_enumopt', full_name='nanopb_enumopt', index=2, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_FIELD_NUMBER = 1010 +nanopb = _descriptor.FieldDescriptor( + name='nanopb', full_name='nanopb', index=3, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_NANOPBOPTIONS = _descriptor.Descriptor( + name='NanoPBOptions', + full_name='NanoPBOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='max_size', full_name='NanoPBOptions.max_size', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_length', full_name='NanoPBOptions.max_length', index=1, + number=14, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_count', full_name='NanoPBOptions.max_count', index=2, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_size', full_name='NanoPBOptions.int_size', index=3, + number=7, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type', full_name='NanoPBOptions.type', index=4, + number=3, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='long_names', full_name='NanoPBOptions.long_names', index=5, + number=4, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_struct', full_name='NanoPBOptions.packed_struct', index=6, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='NanoPBOptions.packed_enum', index=7, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='skip_message', full_name='NanoPBOptions.skip_message', index=8, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='no_unions', full_name='NanoPBOptions.no_unions', index=9, + number=8, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='msgid', full_name='NanoPBOptions.msgid', index=10, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='anonymous_oneof', full_name='NanoPBOptions.anonymous_oneof', index=11, + number=11, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto3', full_name='NanoPBOptions.proto3', index=12, + number=12, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto3_singular_msgs', full_name='NanoPBOptions.proto3_singular_msgs', index=13, + number=21, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_to_string', full_name='NanoPBOptions.enum_to_string', index=14, + number=13, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_length', full_name='NanoPBOptions.fixed_length', index=15, + number=15, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_count', full_name='NanoPBOptions.fixed_count', index=16, + number=16, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='submsg_callback', full_name='NanoPBOptions.submsg_callback', index=17, + number=22, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mangle_names', full_name='NanoPBOptions.mangle_names', index=18, + number=17, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='callback_datatype', full_name='NanoPBOptions.callback_datatype', index=19, + number=18, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=b"pb_callback_t".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='callback_function', full_name='NanoPBOptions.callback_function', index=20, + number=19, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=b"pb_default_field_callback".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='descriptorsize', full_name='NanoPBOptions.descriptorsize', index=21, + number=20, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_has', full_name='NanoPBOptions.default_has', index=22, + number=23, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='include', full_name='NanoPBOptions.include', index=23, + number=24, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='exclude', full_name='NanoPBOptions.exclude', index=24, + number=26, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='package', full_name='NanoPBOptions.package', index=25, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_override', full_name='NanoPBOptions.type_override', index=26, + number=27, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=908, +) + +_NANOPBOPTIONS.fields_by_name['int_size'].enum_type = _INTSIZE +_NANOPBOPTIONS.fields_by_name['type'].enum_type = _FIELDTYPE +_NANOPBOPTIONS.fields_by_name['mangle_names'].enum_type = _TYPENAMEMANGLING +_NANOPBOPTIONS.fields_by_name['descriptorsize'].enum_type = _DESCRIPTORSIZE +_NANOPBOPTIONS.fields_by_name['type_override'].enum_type = google_dot_protobuf_dot_descriptor__pb2._FIELDDESCRIPTORPROTO_TYPE +DESCRIPTOR.message_types_by_name['NanoPBOptions'] = _NANOPBOPTIONS +DESCRIPTOR.enum_types_by_name['FieldType'] = _FIELDTYPE +DESCRIPTOR.enum_types_by_name['IntSize'] = _INTSIZE +DESCRIPTOR.enum_types_by_name['TypenameMangling'] = _TYPENAMEMANGLING +DESCRIPTOR.enum_types_by_name['DescriptorSize'] = _DESCRIPTORSIZE +DESCRIPTOR.extensions_by_name['nanopb_fileopt'] = nanopb_fileopt +DESCRIPTOR.extensions_by_name['nanopb_msgopt'] = nanopb_msgopt +DESCRIPTOR.extensions_by_name['nanopb_enumopt'] = nanopb_enumopt +DESCRIPTOR.extensions_by_name['nanopb'] = nanopb +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NanoPBOptions = _reflection.GeneratedProtocolMessageType('NanoPBOptions', (_message.Message,), { + 'DESCRIPTOR' : _NANOPBOPTIONS, + '__module__' : 'nanopb_pb2' + # @@protoc_insertion_point(class_scope:NanoPBOptions) + }) +_sym_db.RegisterMessage(NanoPBOptions) + +nanopb_fileopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(nanopb_fileopt) +nanopb_msgopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(nanopb_msgopt) +nanopb_enumopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(nanopb_enumopt) +nanopb.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(nanopb) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/python/recipient_pb2.py b/python/recipient_pb2.py index 3bea0040..d5399f5b 100644 --- a/python/recipient_pb2.py +++ b/python/recipient_pb2.py @@ -11,6 +11,7 @@ _sym_db = _symbol_database.Default() +import nanopb_pb2 as nanopb__pb2 DESCRIPTOR = _descriptor.FileDescriptor( @@ -18,8 +19,9 @@ package='waves', syntax='proto3', serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', - serialized_pb=b'\n\x0frecipient.proto\x12\x05waves\"D\n\tRecipient\x12\x19\n\x0fpublic_key_hash\x18\x01 \x01(\x0cH\x00\x12\x0f\n\x05\x61lias\x18\x02 \x01(\tH\x00\x42\x0b\n\trecipientB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' -) + serialized_pb=b'\n\x0frecipient.proto\x12\x05waves\x1a\x0cnanopb.proto\"j\n\tRecipient\x12,\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x42\x11\x92?\x0e\x92\x01\x0b\x63onst char*H\x00\x12\"\n\x05\x61lias\x18\x02 \x01(\tB\x11\x92?\x0e\x92\x01\x0b\x63onst char*H\x00\x42\x0b\n\trecipientB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' + , + dependencies=[nanopb__pb2.DESCRIPTOR,]) @@ -37,14 +39,14 @@ has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), + serialized_options=b'\222?\016\222\001\013const char*', file=DESCRIPTOR), _descriptor.FieldDescriptor( name='alias', full_name='waves.Recipient.alias', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), + serialized_options=b'\222?\016\222\001\013const char*', file=DESCRIPTOR), ], extensions=[ ], @@ -60,8 +62,8 @@ name='recipient', full_name='waves.Recipient.recipient', index=0, containing_type=None, fields=[]), ], - serialized_start=26, - serialized_end=94, + serialized_start=40, + serialized_end=146, ) _RECIPIENT.oneofs_by_name['recipient'].fields.append( @@ -82,4 +84,6 @@ DESCRIPTOR._options = None +_RECIPIENT.fields_by_name['public_key_hash']._options = None +_RECIPIENT.fields_by_name['alias']._options = None # @@protoc_insertion_point(module_scope) diff --git a/python/transaction_pb2.py b/python/transaction_pb2.py index 8a2cec8c..6fd21705 100644 --- a/python/transaction_pb2.py +++ b/python/transaction_pb2.py @@ -11,6 +11,7 @@ _sym_db = _symbol_database.Default() +import nanopb_pb2 as nanopb__pb2 import amount_pb2 as amount__pb2 import recipient_pb2 as recipient__pb2 import order_pb2 as order__pb2 @@ -21,9 +22,9 @@ package='waves', syntax='proto3', serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', - serialized_pb=b'\n\x11transaction.proto\x12\x05waves\x1a\x0c\x61mount.proto\x1a\x0frecipient.proto\x1a\x0border.proto\"L\n\x11SignedTransaction\x12\'\n\x0btransaction\x18\x01 \x01(\x0b\x32\x12.waves.Transaction\x12\x0e\n\x06proofs\x18\x02 \x03(\x0c\"\xa6\x08\n\x0bTransaction\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x03\x66\x65\x65\x18\x03 \x01(\x0b\x32\r.waves.Amount\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x0f\n\x07version\x18\x05 \x01(\x05\x12\x30\n\x07genesis\x18\x65 \x01(\x0b\x32\x1d.waves.GenesisTransactionDataH\x00\x12\x30\n\x07payment\x18\x66 \x01(\x0b\x32\x1d.waves.PaymentTransactionDataH\x00\x12,\n\x05issue\x18g \x01(\x0b\x32\x1b.waves.IssueTransactionDataH\x00\x12\x32\n\x08transfer\x18h \x01(\x0b\x32\x1e.waves.TransferTransactionDataH\x00\x12\x30\n\x07reissue\x18i \x01(\x0b\x32\x1d.waves.ReissueTransactionDataH\x00\x12*\n\x04\x62urn\x18j \x01(\x0b\x32\x1a.waves.BurnTransactionDataH\x00\x12\x32\n\x08\x65xchange\x18k \x01(\x0b\x32\x1e.waves.ExchangeTransactionDataH\x00\x12,\n\x05lease\x18l \x01(\x0b\x32\x1b.waves.LeaseTransactionDataH\x00\x12\x39\n\x0clease_cancel\x18m \x01(\x0b\x32!.waves.LeaseCancelTransactionDataH\x00\x12\x39\n\x0c\x63reate_alias\x18n \x01(\x0b\x32!.waves.CreateAliasTransactionDataH\x00\x12;\n\rmass_transfer\x18o \x01(\x0b\x32\".waves.MassTransferTransactionDataH\x00\x12\x36\n\x10\x64\x61ta_transaction\x18p \x01(\x0b\x32\x1a.waves.DataTransactionDataH\x00\x12\x35\n\nset_script\x18q \x01(\x0b\x32\x1f.waves.SetScriptTransactionDataH\x00\x12\x37\n\x0bsponsor_fee\x18r \x01(\x0b\x32 .waves.SponsorFeeTransactionDataH\x00\x12@\n\x10set_asset_script\x18s \x01(\x0b\x32$.waves.SetAssetScriptTransactionDataH\x00\x12;\n\rinvoke_script\x18t \x01(\x0b\x32\".waves.InvokeScriptTransactionDataH\x00\x12\x42\n\x11update_asset_info\x18u \x01(\x0b\x32%.waves.UpdateAssetInfoTransactionDataH\x00\x42\x06\n\x04\x64\x61ta\"C\n\x16GenesisTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"C\n\x16PaymentTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"u\n\nAttachment\x12\x13\n\tint_value\x18\x01 \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x03 \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\x04 \x01(\tH\x00\x42\x0c\n\nattachment\"\x84\x01\n\x17TransferTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x1d\n\x06\x61mount\x18\x02 \x01(\x0b\x32\r.waves.Amount\x12%\n\nattachment\x18\x03 \x01(\x0b\x32\x11.waves.Attachment\"+\n\x1a\x43reateAliasTransactionData\x12\r\n\x05\x61lias\x18\x01 \x01(\t\"\xc7\x01\n\x13\x44\x61taTransactionData\x12\x32\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32$.waves.DataTransactionData.DataEntry\x1a|\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\n \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x0b \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x0c \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\r \x01(\tH\x00\x42\x07\n\x05value\"\xd5\x01\n\x1bMassTransferTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12>\n\ttransfers\x18\x02 \x03(\x0b\x32+.waves.MassTransferTransactionData.Transfer\x12%\n\nattachment\x18\x03 \x01(\x0b\x32\x11.waves.Attachment\x1a=\n\x08Transfer\x12!\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"K\n\x14LeaseTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\".\n\x1aLeaseCancelTransactionData\x12\x10\n\x08lease_id\x18\x01 \x01(\x0c\":\n\x13\x42urnTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\"\x7f\n\x14IssueTransactionData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x03\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x05\x12\x12\n\nreissuable\x18\x05 \x01(\x08\x12\x0e\n\x06script\x18\x06 \x01(\x0c\"Q\n\x16ReissueTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nreissuable\x18\x02 \x01(\x08\"A\n\x1dSetAssetScriptTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06script\x18\x02 \x01(\x0c\"*\n\x18SetScriptTransactionData\x12\x0e\n\x06script\x18\x01 \x01(\x0c\"\x89\x01\n\x17\x45xchangeTransactionData\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x03\x12\r\n\x05price\x18\x02 \x01(\x03\x12\x17\n\x0f\x62uy_matcher_fee\x18\x03 \x01(\x03\x12\x18\n\x10sell_matcher_fee\x18\x04 \x01(\x03\x12\x1c\n\x06orders\x18\x05 \x03(\x0b\x32\x0c.waves.Order\";\n\x19SponsorFeeTransactionData\x12\x1e\n\x07min_fee\x18\x01 \x01(\x0b\x32\r.waves.Amount\"v\n\x1bInvokeScriptTransactionData\x12\x1f\n\x05\x64_app\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x15\n\rfunction_call\x18\x02 \x01(\x0c\x12\x1f\n\x08payments\x18\x03 \x03(\x0b\x32\r.waves.Amount\"U\n\x1eUpdateAssetInfoTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\tB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' + serialized_pb=b'\n\x11transaction.proto\x12\x05waves\x1a\x0cnanopb.proto\x1a\x0c\x61mount.proto\x1a\x0frecipient.proto\x1a\x0border.proto\"L\n\x11SignedTransaction\x12\'\n\x0btransaction\x18\x01 \x01(\x0b\x32\x12.waves.Transaction\x12\x0e\n\x06proofs\x18\x02 \x03(\x0c\"\xae\x08\n\x0bTransaction\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x03\x66\x65\x65\x18\x03 \x01(\x0b\x32\r.waves.Amount\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x0f\n\x07version\x18\x05 \x01(\x05\x12\x30\n\x07genesis\x18\x65 \x01(\x0b\x32\x1d.waves.GenesisTransactionDataH\x00\x12\x30\n\x07payment\x18\x66 \x01(\x0b\x32\x1d.waves.PaymentTransactionDataH\x00\x12,\n\x05issue\x18g \x01(\x0b\x32\x1b.waves.IssueTransactionDataH\x00\x12\x32\n\x08transfer\x18h \x01(\x0b\x32\x1e.waves.TransferTransactionDataH\x00\x12\x30\n\x07reissue\x18i \x01(\x0b\x32\x1d.waves.ReissueTransactionDataH\x00\x12*\n\x04\x62urn\x18j \x01(\x0b\x32\x1a.waves.BurnTransactionDataH\x00\x12\x32\n\x08\x65xchange\x18k \x01(\x0b\x32\x1e.waves.ExchangeTransactionDataH\x00\x12,\n\x05lease\x18l \x01(\x0b\x32\x1b.waves.LeaseTransactionDataH\x00\x12\x39\n\x0clease_cancel\x18m \x01(\x0b\x32!.waves.LeaseCancelTransactionDataH\x00\x12\x39\n\x0c\x63reate_alias\x18n \x01(\x0b\x32!.waves.CreateAliasTransactionDataH\x00\x12;\n\rmass_transfer\x18o \x01(\x0b\x32\".waves.MassTransferTransactionDataH\x00\x12\x36\n\x10\x64\x61ta_transaction\x18p \x01(\x0b\x32\x1a.waves.DataTransactionDataH\x00\x12\x35\n\nset_script\x18q \x01(\x0b\x32\x1f.waves.SetScriptTransactionDataH\x00\x12\x37\n\x0bsponsor_fee\x18r \x01(\x0b\x32 .waves.SponsorFeeTransactionDataH\x00\x12@\n\x10set_asset_script\x18s \x01(\x0b\x32$.waves.SetAssetScriptTransactionDataH\x00\x12;\n\rinvoke_script\x18t \x01(\x0b\x32\".waves.InvokeScriptTransactionDataH\x00\x12\x42\n\x11update_asset_info\x18u \x01(\x0b\x32%.waves.UpdateAssetInfoTransactionDataH\x00:\x06\x92?\x03\xb0\x01\x01\x42\x06\n\x04\x64\x61ta\"C\n\x16GenesisTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"C\n\x16PaymentTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"q\n\x17TransferTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x1d\n\x06\x61mount\x18\x02 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nattachment\x18\x03 \x01(\x0c\"+\n\x1a\x43reateAliasTransactionData\x12\r\n\x05\x61lias\x18\x01 \x01(\t\"\xc7\x01\n\x13\x44\x61taTransactionData\x12\x32\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32$.waves.DataTransactionData.DataEntry\x1a|\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\n \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x0b \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x0c \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\r \x01(\tH\x00\x42\x07\n\x05value\"\xcb\x01\n\x1bMassTransferTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12>\n\ttransfers\x18\x02 \x03(\x0b\x32+.waves.MassTransferTransactionData.Transfer\x12\x12\n\nattachment\x18\x03 \x01(\x0c\x1a\x46\n\x08Transfer\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03:\x05\x92?\x02\x30\x01\"K\n\x14LeaseTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\".\n\x1aLeaseCancelTransactionData\x12\x10\n\x08lease_id\x18\x01 \x01(\x0c\":\n\x13\x42urnTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\"\x7f\n\x14IssueTransactionData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x03\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x05\x12\x12\n\nreissuable\x18\x05 \x01(\x08\x12\x0e\n\x06script\x18\x06 \x01(\x0c\"Q\n\x16ReissueTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nreissuable\x18\x02 \x01(\x08\"A\n\x1dSetAssetScriptTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06script\x18\x02 \x01(\x0c\"*\n\x18SetScriptTransactionData\x12\x0e\n\x06script\x18\x01 \x01(\x0c\"\x89\x01\n\x17\x45xchangeTransactionData\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x03\x12\r\n\x05price\x18\x02 \x01(\x03\x12\x17\n\x0f\x62uy_matcher_fee\x18\x03 \x01(\x03\x12\x18\n\x10sell_matcher_fee\x18\x04 \x01(\x03\x12\x1c\n\x06orders\x18\x05 \x03(\x0b\x32\x0c.waves.Order\";\n\x19SponsorFeeTransactionData\x12\x1e\n\x07min_fee\x18\x01 \x01(\x0b\x32\r.waves.Amount\"v\n\x1bInvokeScriptTransactionData\x12\x1f\n\x05\x64_app\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x15\n\rfunction_call\x18\x02 \x01(\x0c\x12\x1f\n\x08payments\x18\x03 \x03(\x0b\x32\r.waves.Amount\"U\n\x1eUpdateAssetInfoTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\tB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' , - dependencies=[amount__pb2.DESCRIPTOR,recipient__pb2.DESCRIPTOR,order__pb2.DESCRIPTOR,]) + dependencies=[nanopb__pb2.DESCRIPTOR,amount__pb2.DESCRIPTOR,recipient__pb2.DESCRIPTOR,order__pb2.DESCRIPTOR,]) @@ -61,8 +62,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=72, - serialized_end=148, + serialized_start=86, + serialized_end=162, ) @@ -233,7 +234,7 @@ nested_types=[], enum_types=[ ], - serialized_options=None, + serialized_options=b'\222?\003\260\001\001', is_extendable=False, syntax='proto3', extension_ranges=[], @@ -242,8 +243,8 @@ name='data', full_name='waves.Transaction.data', index=0, containing_type=None, fields=[]), ], - serialized_start=151, - serialized_end=1213, + serialized_start=165, + serialized_end=1235, ) @@ -280,8 +281,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1215, - serialized_end=1282, + serialized_start=1237, + serialized_end=1304, ) @@ -318,63 +319,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1284, - serialized_end=1351, -) - - -_ATTACHMENT = _descriptor.Descriptor( - name='Attachment', - full_name='waves.Attachment', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='int_value', full_name='waves.Attachment.int_value', index=0, - number=1, type=3, cpp_type=2, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='bool_value', full_name='waves.Attachment.bool_value', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='binary_value', full_name='waves.Attachment.binary_value', index=2, - number=3, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='string_value', full_name='waves.Attachment.string_value', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=b"".decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - _descriptor.OneofDescriptor( - name='attachment', full_name='waves.Attachment.attachment', - index=0, containing_type=None, fields=[]), - ], - serialized_start=1353, - serialized_end=1470, + serialized_start=1306, + serialized_end=1373, ) @@ -401,8 +347,8 @@ serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='attachment', full_name='waves.TransferTransactionData.attachment', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -418,8 +364,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1473, - serialized_end=1605, + serialized_start=1375, + serialized_end=1488, ) @@ -449,8 +395,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1607, - serialized_end=1650, + serialized_start=1490, + serialized_end=1533, ) @@ -511,8 +457,8 @@ name='value', full_name='waves.DataTransactionData.DataEntry.value', index=0, containing_type=None, fields=[]), ], - serialized_start=1728, - serialized_end=1852, + serialized_start=1611, + serialized_end=1735, ) _DATATRANSACTIONDATA = _descriptor.Descriptor( @@ -541,8 +487,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1653, - serialized_end=1852, + serialized_start=1536, + serialized_end=1735, ) @@ -554,7 +500,7 @@ containing_type=None, fields=[ _descriptor.FieldDescriptor( - name='address', full_name='waves.MassTransferTransactionData.Transfer.address', index=0, + name='recipient', full_name='waves.MassTransferTransactionData.Transfer.recipient', index=0, number=1, type=11, cpp_type=10, label=1, has_default_value=False, default_value=None, message_type=None, enum_type=None, containing_type=None, @@ -573,14 +519,14 @@ nested_types=[], enum_types=[ ], - serialized_options=None, + serialized_options=b'\222?\0020\001', is_extendable=False, syntax='proto3', extension_ranges=[], oneofs=[ ], - serialized_start=2007, - serialized_end=2068, + serialized_start=1871, + serialized_end=1941, ) _MASSTRANSFERTRANSACTIONDATA = _descriptor.Descriptor( @@ -606,8 +552,8 @@ serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='attachment', full_name='waves.MassTransferTransactionData.attachment', index=2, - number=3, type=11, cpp_type=10, label=1, - has_default_value=False, default_value=None, + number=3, type=12, cpp_type=9, label=1, + has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, serialized_options=None, file=DESCRIPTOR), @@ -623,8 +569,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1855, - serialized_end=2068, + serialized_start=1738, + serialized_end=1941, ) @@ -661,8 +607,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2070, - serialized_end=2145, + serialized_start=1943, + serialized_end=2018, ) @@ -692,8 +638,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2147, - serialized_end=2193, + serialized_start=2020, + serialized_end=2066, ) @@ -723,8 +669,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2195, - serialized_end=2253, + serialized_start=2068, + serialized_end=2126, ) @@ -789,8 +735,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2255, - serialized_end=2382, + serialized_start=2128, + serialized_end=2255, ) @@ -827,8 +773,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2384, - serialized_end=2465, + serialized_start=2257, + serialized_end=2338, ) @@ -865,8 +811,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2467, - serialized_end=2532, + serialized_start=2340, + serialized_end=2405, ) @@ -896,8 +842,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2534, - serialized_end=2576, + serialized_start=2407, + serialized_end=2449, ) @@ -955,8 +901,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2579, - serialized_end=2716, + serialized_start=2452, + serialized_end=2589, ) @@ -986,8 +932,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2718, - serialized_end=2777, + serialized_start=2591, + serialized_end=2650, ) @@ -1031,8 +977,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2779, - serialized_end=2897, + serialized_start=2652, + serialized_end=2770, ) @@ -1076,8 +1022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2899, - serialized_end=2984, + serialized_start=2772, + serialized_end=2857, ) _SIGNEDTRANSACTION.fields_by_name['transaction'].message_type = _TRANSACTION @@ -1150,21 +1096,8 @@ _TRANSACTION.oneofs_by_name['data'].fields.append( _TRANSACTION.fields_by_name['update_asset_info']) _TRANSACTION.fields_by_name['update_asset_info'].containing_oneof = _TRANSACTION.oneofs_by_name['data'] -_ATTACHMENT.oneofs_by_name['attachment'].fields.append( - _ATTACHMENT.fields_by_name['int_value']) -_ATTACHMENT.fields_by_name['int_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] -_ATTACHMENT.oneofs_by_name['attachment'].fields.append( - _ATTACHMENT.fields_by_name['bool_value']) -_ATTACHMENT.fields_by_name['bool_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] -_ATTACHMENT.oneofs_by_name['attachment'].fields.append( - _ATTACHMENT.fields_by_name['binary_value']) -_ATTACHMENT.fields_by_name['binary_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] -_ATTACHMENT.oneofs_by_name['attachment'].fields.append( - _ATTACHMENT.fields_by_name['string_value']) -_ATTACHMENT.fields_by_name['string_value'].containing_oneof = _ATTACHMENT.oneofs_by_name['attachment'] _TRANSFERTRANSACTIONDATA.fields_by_name['recipient'].message_type = recipient__pb2._RECIPIENT _TRANSFERTRANSACTIONDATA.fields_by_name['amount'].message_type = amount__pb2._AMOUNT -_TRANSFERTRANSACTIONDATA.fields_by_name['attachment'].message_type = _ATTACHMENT _DATATRANSACTIONDATA_DATAENTRY.containing_type = _DATATRANSACTIONDATA _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'].fields.append( _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['int_value']) @@ -1179,10 +1112,9 @@ _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['string_value']) _DATATRANSACTIONDATA_DATAENTRY.fields_by_name['string_value'].containing_oneof = _DATATRANSACTIONDATA_DATAENTRY.oneofs_by_name['value'] _DATATRANSACTIONDATA.fields_by_name['data'].message_type = _DATATRANSACTIONDATA_DATAENTRY -_MASSTRANSFERTRANSACTIONDATA_TRANSFER.fields_by_name['address'].message_type = recipient__pb2._RECIPIENT +_MASSTRANSFERTRANSACTIONDATA_TRANSFER.fields_by_name['recipient'].message_type = recipient__pb2._RECIPIENT _MASSTRANSFERTRANSACTIONDATA_TRANSFER.containing_type = _MASSTRANSFERTRANSACTIONDATA _MASSTRANSFERTRANSACTIONDATA.fields_by_name['transfers'].message_type = _MASSTRANSFERTRANSACTIONDATA_TRANSFER -_MASSTRANSFERTRANSACTIONDATA.fields_by_name['attachment'].message_type = _ATTACHMENT _LEASETRANSACTIONDATA.fields_by_name['recipient'].message_type = recipient__pb2._RECIPIENT _BURNTRANSACTIONDATA.fields_by_name['asset_amount'].message_type = amount__pb2._AMOUNT _REISSUETRANSACTIONDATA.fields_by_name['asset_amount'].message_type = amount__pb2._AMOUNT @@ -1194,7 +1126,6 @@ DESCRIPTOR.message_types_by_name['Transaction'] = _TRANSACTION DESCRIPTOR.message_types_by_name['GenesisTransactionData'] = _GENESISTRANSACTIONDATA DESCRIPTOR.message_types_by_name['PaymentTransactionData'] = _PAYMENTTRANSACTIONDATA -DESCRIPTOR.message_types_by_name['Attachment'] = _ATTACHMENT DESCRIPTOR.message_types_by_name['TransferTransactionData'] = _TRANSFERTRANSACTIONDATA DESCRIPTOR.message_types_by_name['CreateAliasTransactionData'] = _CREATEALIASTRANSACTIONDATA DESCRIPTOR.message_types_by_name['DataTransactionData'] = _DATATRANSACTIONDATA @@ -1240,13 +1171,6 @@ }) _sym_db.RegisterMessage(PaymentTransactionData) -Attachment = _reflection.GeneratedProtocolMessageType('Attachment', (_message.Message,), { - 'DESCRIPTOR' : _ATTACHMENT, - '__module__' : 'transaction_pb2' - # @@protoc_insertion_point(class_scope:waves.Attachment) - }) -_sym_db.RegisterMessage(Attachment) - TransferTransactionData = _reflection.GeneratedProtocolMessageType('TransferTransactionData', (_message.Message,), { 'DESCRIPTOR' : _TRANSFERTRANSACTIONDATA, '__module__' : 'transaction_pb2' @@ -1370,4 +1294,6 @@ DESCRIPTOR._options = None +_TRANSACTION._options = None +_MASSTRANSFERTRANSACTIONDATA_TRANSFER._options = None # @@protoc_insertion_point(module_scope) diff --git a/src/crypto/stream_eddsa_sign.c b/src/crypto/stream_eddsa_sign.c index 48a3c1d7..a844e277 100644 --- a/src/crypto/stream_eddsa_sign.c +++ b/src/crypto/stream_eddsa_sign.c @@ -19,6 +19,7 @@ ********************************************************************************/ #include "stream_eddsa_sign.h" +#include "../main.h" static uint8_t const C_cx_Ed25519_a[] = { 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -229,7 +230,7 @@ void stream_eddsa_sign_step3(streamEddsaContext_t *eddsa_context) { unsigned int hsize = 2 * size; cx_hash(&eddsa_context->data_hash_ctx.header, CX_LAST, NULL, 0, - eddsa_context->first_data_hash, 32); + tmp_ctx.signing_context.first_data_hash, 32); cx_hash(&eddsa_context->hash_ctx.header, CX_LAST, NULL, 0, scal, 64); cx_encode_int(scal, hsize); cx_math_modm(scal, hsize, domain->n, size); @@ -274,7 +275,8 @@ int stream_eddsa_sign_step5(streamEddsaContext_t *eddsa_context, unsigned char second_data_hash[64]; cx_hash(&eddsa_context->data_hash_ctx.header, CX_LAST, NULL, 0, second_data_hash, 32); - if (os_memcmp(&eddsa_context->first_data_hash, &second_data_hash, 32) != 0) { + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, &second_data_hash, + 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } cx_hash(&eddsa_context->hash_ctx.header, CX_LAST, NULL, 0, scal, 64); diff --git a/src/crypto/stream_eddsa_sign.h b/src/crypto/stream_eddsa_sign.h index 6ee71c51..461360a4 100644 --- a/src/crypto/stream_eddsa_sign.h +++ b/src/crypto/stream_eddsa_sign.h @@ -38,7 +38,6 @@ typedef struct streamEddsaContext_t { } u; cx_sha512_t hash_ctx; cx_blake2b_t data_hash_ctx; - unsigned char first_data_hash[32]; } streamEddsaContext_t; void stream_eddsa_sign_step1(streamEddsaContext_t *eddsa_context, diff --git a/src/crypto/waves.c b/src/crypto/waves.c index 89669464..a790945f 100644 --- a/src/crypto/waves.c +++ b/src/crypto/waves.c @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ - +#include "main.h" #include "waves.h" #include "ledger_crypto.h" #include "stream_eddsa_sign.h" @@ -29,7 +29,7 @@ void waves_secure_hash(const uint8_t *message, size_t message_len, } // Build waves address from the curve25519 public key, check -// https://github.com/wavesplatform/Waves/wiki/Data-Structures#address +// https://docs.wavesprotocol.org/ru/blockchain/binary-format/address-binary-format void waves_public_key_to_address(const ed25519_public_key public_key, const unsigned char network_byte, unsigned char *output) { @@ -50,6 +50,20 @@ void waves_public_key_to_address(const ed25519_public_key public_key, b58enc((char *)output, &length, address, 26); } +void waves_public_key_hash_to_address( + const ed25519_public_key_hash public_key_hash, + const unsigned char network_byte, unsigned char *output) { + uint8_t address[26]; + uint8_t checksum[32]; + address[0] = 0x01; + address[1] = network_byte; + os_memmove(&address[2], public_key_hash, 20); + waves_secure_hash(address, 22, checksum); + os_memmove(&address[22], checksum, 4); + size_t length = 36; + b58enc((char *)output, &length, address, 26); +} + void copy_in_reverse_order(unsigned char *to, const unsigned char *from, const unsigned int len) { for (uint16_t i = 0; i < len; i++) { diff --git a/src/crypto/waves.h b/src/crypto/waves.h index 8609b3df..29023f38 100644 --- a/src/crypto/waves.h +++ b/src/crypto/waves.h @@ -30,13 +30,16 @@ #include "stream_eddsa_sign.h" typedef unsigned char ed25519_signature[64]; +typedef unsigned char ed25519_public_key_hash[20]; typedef unsigned char ed25519_public_key[32]; typedef unsigned char ed25519_secret_key[32]; void waves_public_key_to_address(const ed25519_public_key public_key, const unsigned char network_byte, unsigned char *output); +void waves_public_key_hash_to_address( + const ed25519_public_key_hash public_key_hash, + const unsigned char network_byte, unsigned char *output); void copy_in_reverse_order(unsigned char *to, const unsigned char *from, const unsigned int len); - #endif diff --git a/src/main.c b/src/main.c index d0a373c8..269d45f5 100644 --- a/src/main.c +++ b/src/main.c @@ -30,20 +30,9 @@ #include "os.h" #include "cx.h" #include "os_io_seproxyhal.h" -#include "nanopb/pb_custom.h" -#include "nanopb/pb_decode.h" -#include "nanopb/pb_encode.h" -#include "nanopb_stubs/transaction.pb.h" - -#define OFFSET_CLA 0 -#define OFFSET_INS 1 -#define OFFSET_P1 2 -#define OFFSET_P2 3 -#define OFFSET_LC 4 -#define OFFSET_CDATA 5 + // Temporary area to store stuff and reuse the same memory tmpContext_t tmp_ctx; -uiContext_t ui_context; // Non-volatile storage for the wallet app's stuff internal_storage_t const N_storage_real; @@ -55,6 +44,18 @@ unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; #error This application only supports the Ledger Nano S, Nano X and the Ledger Blue #endif +extern void _ebss; + +// Return true if there is less than MIN_BSS_STACK_GAP bytes available in the +// stack +void check_stack_overflow(int step) { + uint32_t stack_top = 0; + // PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: + // %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - + // ((uintptr_t)&_ebss)); + PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); +} + unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: @@ -124,7 +125,6 @@ void hash_stream_data(uint8_t chunk_data_size, uint8_t chunk_data_start_index) { // from the button handler after the user verifies the transaction. void make_sign_step(uint8_t chunk_data_start_index, uint8_t chunk_data_size) { - PRINTF("make_sign_step start step: %d\n", tmp_ctx.signing_context.step); if (tmp_ctx.signing_context.step == 1) { cx_ecfp_public_key_t public_key; cx_ecfp_private_key_t private_key; @@ -152,15 +152,12 @@ void make_sign_step(uint8_t chunk_data_start_index, uint8_t chunk_data_size) { // chunk_data_size will be false if (tmp_ctx.signing_context.data_read == tmp_ctx.signing_context.data_size) { - os_memmove(ui_context.id, - tmp_ctx.signing_context.eddsa_context.first_data_hash, 32); tmp_ctx.signing_context.step = 5; + return; } } } - PRINTF("make_sign_step end step: %d\n", tmp_ctx.signing_context.step); } - void make_allowed_sign_steps() { uint8_t chunk_data_start_index = 5; uint8_t chunk_data_size = G_io_apdu_buffer[4]; @@ -181,7 +178,8 @@ void make_allowed_sign_steps() { deserialize_uint32_t(&G_io_apdu_buffer[29]); } - while (tmp_ctx.signing_context.chunk_used < chunk_data_size) { + while (tmp_ctx.signing_context.chunk_used < chunk_data_size && + tmp_ctx.signing_context.step < 5) { make_sign_step(chunk_data_start_index, chunk_data_size); } // else wait for next chunk @@ -190,14 +188,11 @@ void make_allowed_sign_steps() { // like // https://github.com/lenondupe/ledger-app-stellar/blob/master/src/main.c#L1784 uint32_t set_result_sign() { - uint8_t signature[64]; - - stream_eddsa_sign_step5(&tmp_ctx.signing_context.eddsa_context, signature); + tmp_ctx.signing_context.signature[63] |= tmp_ctx.signing_context.sign_bit; + os_memmove((char *)G_io_apdu_buffer, tmp_ctx.signing_context.signature, + sizeof(tmp_ctx.signing_context.signature)); - signature[63] |= tmp_ctx.signing_context.sign_bit; - os_memmove((char *)G_io_apdu_buffer, signature, sizeof(signature)); - - PRINTF("Signature:\n%.*H\n", 64, signature); + PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); init_context(); @@ -246,79 +241,70 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, (G_io_apdu_buffer[2] != P1_LAST)) { THROW(SW_INCORRECT_P1_P2); } - - if (tmp_ctx.signing_context.step == 5) { - THROW(SW_INCORRECT_P1_P2); - } - if (tmp_ctx.signing_context.step > 0) { - tmp_ctx.signing_context.chunk += 1; - } else { - //show_processing(); - os_memset((unsigned char *)&ui_context, 0, sizeof(uiContext_t)); - tmp_ctx.signing_context.step = 1; - tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; - } - - uint8_t chunk_data_start_index = 5; - uint8_t chunk_data_size = G_io_apdu_buffer[4]; - - if (tmp_ctx.signing_context.chunk == 0) { - chunk_data_start_index += 28; - chunk_data_size -= 28; - - // then there is the bip32 path in the first chunk - first 20 bytes of data - read_path_from_bytes(G_io_apdu_buffer + 5, - (uint32_t *)tmp_ctx.signing_context.bip32); - - tmp_ctx.signing_context.amount_decimals = G_io_apdu_buffer[25]; - tmp_ctx.signing_context.fee_decimals = G_io_apdu_buffer[26]; - tmp_ctx.signing_context.data_type = G_io_apdu_buffer[27]; - tmp_ctx.signing_context.data_version = G_io_apdu_buffer[28]; - tmp_ctx.signing_context.data_size = - deserialize_uint32_t(&G_io_apdu_buffer[29]); - } - - uint8_t status; - uint16_t total_message_size = tmp_ctx.signing_context.data_size; - - PRINTF("total_message_size: %d\n", total_message_size); - - pb_istream_from_apdu_ctx_t pb_apdu_ctx; - - waves_Transaction tx = waves_Transaction_init_zero; - - /* Create an input stream that will deserialize the nanopb message coming from successives APDUs */ - pb_istream_t stream = pb_istream_from_apdu(&pb_apdu_ctx, G_io_apdu_buffer + chunk_data_start_index, G_io_apdu_buffer[4] - chunk_data_start_index + 5, total_message_size); - - /* Now we are ready to decode the message. */ - status = pb_decode(&stream, waves_Transaction_fields, &tx); - /* Check for errors... */ - if (!status) - { - PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); - THROW(0x6D00); - } - - THROW(0x9000); - break; - - /*tmp_ctx.signing_context.chunk_used = 0; - ui_context.chunk_used = 0; - if (G_io_apdu_buffer[2] == P1_LAST) { + if (tmp_ctx.signing_context.step <= 5) { + if (tmp_ctx.signing_context.step > 0) { + tmp_ctx.signing_context.chunk += 1; + } else { + PRINTF("make_sign_steps start\n"); + show_processing(); + tmp_ctx.signing_context.step = 1; + tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; + } + tmp_ctx.signing_context.chunk_used = 0; make_allowed_sign_steps(); if (tmp_ctx.signing_context.step == 5) { - //make_allowed_ui_steps(true); - show_sign_ui(); - *flags |= IO_ASYNCH_REPLY; + stream_eddsa_sign_step5(&tmp_ctx.signing_context.eddsa_context, + tmp_ctx.signing_context.signature); + tmp_ctx.signing_context.step = 6; + PRINTF("make_sign_steps end\n"); + os_memset(&tmp_ctx.signing_context.ui, 0, + sizeof(tmp_ctx.signing_context.ui)); + cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); } else { + THROW(SW_OK); + // wait for next chunk for sign + } + } + if (G_io_apdu_buffer[2] == P1_LAST) { + make_allowed_ui_steps(true); + if (tmp_ctx.signing_context.step != 7) { THROW(SW_DEPRECATED_SIGN_PROTOCOL); } } else { - make_allowed_sign_steps(); - //make_allowed_ui_steps(false); - THROW(SW_OK); - }*/ - + make_allowed_ui_steps(false); + } + if (tmp_ctx.signing_context.step == 7) { + unsigned char third_data_hash[64]; + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, + third_data_hash, 32); + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + &third_data_hash, 32) != 0) { + THROW(SW_SIGN_DATA_NOT_MATCH); + } + size_t length = 45; + if (!b58enc((char *)tmp_ctx.signing_context.ui.txid, &length, + (const void *)&tmp_ctx.signing_context.first_data_hash, + 32)) { + THROW(SW_CONDITIONS_NOT_SATISFIED); + } + // convert sender public key to address + waves_public_key_to_address(tmp_ctx.signing_context.ui.from, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.from); + if (tmp_ctx.signing_context.ui.pkhash) { + waves_public_key_hash_to_address( + tmp_ctx.signing_context.ui.line3, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } + if (tmp_ctx.signing_context.data_version > 2) { + show_sign_protobuf_ui(); + } else { + show_sign_ui(); + } + *flags |= IO_ASYNCH_REPLY; + } + THROW(SW_OK); } break; case INS_GET_PUBLIC_KEY: { @@ -432,7 +418,7 @@ static void waves_main(void) { THROW(SW_SECURITY_STATUS_NOT_SATISFIED); } - PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); + // PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); // Call the Apdu handler, handle_apdu(&flags, &tx, rx); @@ -577,4 +563,4 @@ __attribute__((section(".boot"))) int main(void) { } app_exit(); return 0; -} +} \ No newline at end of file diff --git a/src/main.h b/src/main.h index 9b5d5e48..f6071514 100644 --- a/src/main.h +++ b/src/main.h @@ -34,7 +34,6 @@ #define P1_NON_CONFIRM 0x00 // Don't show address confirmation #define P1_LAST 0x80 // Parameter 1 = End of Bytes to Sign (finalize) #define P1_MORE 0x00 // Parameter 1 = More bytes coming -#define PB_FIRST_BYTE 0x0A //First byte of protobuf transaction message #define SW_OK 0x9000 #define SW_USER_CANCELLED 0x9100 @@ -59,46 +58,73 @@ typedef struct internal_storage_t { extern internal_storage_t const N_storage_real; #define N_storage (*(volatile internal_storage_t *)PIC(&N_storage_real)) +// A place to store information and parser state of the byte message +typedef struct uiByte_t { + unsigned char buffer[150]; + uint8_t step; + uint8_t wait_in_buffer; + uint8_t buffer_used; + uint32_t chunk_used; + uint16_t alias_size; + uint16_t attachment_size; +} uiByte_t; + +// A place to store information and parser state of the protobuf message +typedef struct uiProtobuf_t { + uint16_t read_offset; // nanopb read offset, everything before it has been + // succesfully decoded + uint16_t bytes_stored; // number of bytes currently stored in "data" + uint16_t total_size; // total size of the nanopb structure being received + uint16_t total_received; // number of bytes received since decoding began + uint16_t total_read; // number of bytes readed since decoding began + uint8_t data[150]; // size of the biggest nanopb element serialized +} uiProtobuf_t; + // A place to store information about the transaction // for displaying to the user when requesting approval // 44 for address/id and +1 for \0 typedef struct uiContext_t { + unsigned char tmp[10]; + unsigned char txid[45]; + unsigned char from[35]; + unsigned char fee_amount[20]; + unsigned char fee_asset[45]; unsigned char line1[45]; unsigned char line2[45]; unsigned char line3[45]; unsigned char line4[45]; unsigned char line5[45]; - unsigned char line6[45]; - unsigned char line7[45]; - unsigned char line8[45]; - unsigned char id[32]; - unsigned char buffer[150]; - unsigned char tmp[50]; - uint8_t step; - uint8_t wait_in_buffer; - uint8_t buffer_used; - uint32_t chunk_used; - uint16_t alias_size; - uint16_t attachment_size; + bool pkhash; + cx_blake2b_t hash_ctx; + union { + uiByte_t byte; + uiProtobuf_t proto; + }; bool finished; } uiContext_t; // A place to store data during the signing typedef struct signingContext_t { - uint32_t bip32[5]; unsigned char sign_bit; unsigned char amount_decimals; unsigned char fee_decimals; unsigned char data_type; unsigned char data_version; unsigned char network_byte; - uint32_t data_size; + unsigned char signature[64]; + unsigned char first_data_hash[32]; + uint8_t step; + uint8_t sign_from; + uint32_t bip32[5]; uint32_t data_read; + uint32_t data_size; uint32_t chunk_used; uint32_t chunk; - uint8_t step; - uint8_t sign_from; - streamEddsaContext_t eddsa_context; + union { + uiContext_t ui; + streamEddsaContext_t eddsa_context; + }; + } signingContext_t; // A place to store data during the confirming the address @@ -112,15 +138,15 @@ typedef union { addressesContext_t address_context; } tmpContext_t; -extern uiContext_t ui_context; - extern tmpContext_t tmp_ctx; // Temporary area to store stuff bool get_curve25519_public_key_for_path(const uint32_t *path, cx_ecfp_public_key_t *public_key); void init_context(); +void init_sign(); +void make_allowed_sign_steps(); uint32_t set_result_get_address(); uint32_t set_result_sign(); -#endif +#endif \ No newline at end of file diff --git a/src/nanopb/pb.h b/src/nanopb/pb.h index fce1f1b6..7f5b6433 100644 --- a/src/nanopb/pb.h +++ b/src/nanopb/pb.h @@ -11,7 +11,7 @@ *****************************************************************/ /* Enable support for dynamically allocated fields */ -/*#define PB_ENABLE_MALLOC 1 */ +/* #define PB_ENABLE_MALLOC 1 */ /* Define this if your CPU / compiler combination does not support * unaligned memory access to packed structures. */ @@ -21,11 +21,8 @@ * A compiler warning will tell if you need this. */ /* #define PB_MAX_REQUIRED_FIELDS 256 */ -/* Add support for tag numbers > 255 and fields larger than 255 bytes. */ -/* #define PB_FIELD_16BIT 1 */ - /* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */ -#define PB_FIELD_32BIT 1 +/* #define PB_FIELD_32BIT 1 */ /* Disable support for error messages in order to save some code space. */ /* #define PB_NO_ERRMSG 1 */ @@ -33,20 +30,37 @@ /* Disable support for custom streams (support only memory buffers). */ /* #define PB_BUFFER_ONLY 1 */ -/* Switch back to the old-style callback function signature. - * This was the default until nanopb-0.2.1. */ -/* #define PB_OLD_CALLBACK_STYLE */ +/* Disable support for 64-bit datatypes, for compilers without int64_t + or to save some code space. */ +/* #define PB_WITHOUT_64BIT 1 */ + +/* Set the fieldinfo width for all messages using automatic width + * selection. Valid values are 2, 4 and 8. Usually even if you need + * to change the width manually for some reason, it is preferrable + * to do so through the descriptorsize option in .options file. */ +/* #define PB_FIELDINFO_WIDTH 4 */ + +/* Don't encode scalar arrays as packed. This is only to be used when + * the decoder on the receiving side cannot process packed scalar arrays. + * Such example is older protobuf.js. */ +/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */ + +/* Enable conversion of doubles to floats for platforms that do not + * support 64-bit doubles. Most commonly AVR. */ +/* #define PB_CONVERT_DOUBLE_FLOAT 1 */ +/* Check whether incoming strings are valid UTF-8 sequences. Slows down + * the string processing slightly and slightly increases code size. */ +/* #define PB_VALIDATE_UTF8 1 */ /****************************************************************** * You usually don't need to change anything below this line. * * Feel free to look around and use the defined macros, though. * ******************************************************************/ - /* Version of the nanopb library. Just in case you want to check it in * your own program. */ -#define NANOPB_VERSION nanopb-0.4.0-dev +#define NANOPB_VERSION nanopb - 0.4.0 /* Include all the system headers needed by nanopb. You will need the * definitions of the following: @@ -66,40 +80,45 @@ #include #include #include +#include #ifdef PB_ENABLE_MALLOC #include #endif #endif +#ifdef __cplusplus +extern "C" { +#endif + /* Macro for defining packed structures (compiler dependent). * This just reduces memory requirements, but is not required. */ #if defined(PB_NO_PACKED_STRUCTS) - /* Disable struct packing */ -# define PB_PACKED_STRUCT_START -# define PB_PACKED_STRUCT_END -# define pb_packed +/* Disable struct packing */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed #elif defined(__GNUC__) || defined(__clang__) - /* For GCC and clang */ -# define PB_PACKED_STRUCT_START -# define PB_PACKED_STRUCT_END -# define pb_packed __attribute__((packed)) +/* For GCC and clang */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed __attribute__((packed)) #elif defined(__ICCARM__) || defined(__CC_ARM) - /* For IAR ARM and Keil MDK-ARM compilers */ -# define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") -# define PB_PACKED_STRUCT_END _Pragma("pack(pop)") -# define pb_packed +/* For IAR ARM and Keil MDK-ARM compilers */ +#define PB_PACKED_STRUCT_START _Pragma("pack(push, 1)") +#define PB_PACKED_STRUCT_END _Pragma("pack(pop)") +#define pb_packed #elif defined(_MSC_VER) && (_MSC_VER >= 1500) - /* For Microsoft Visual C++ */ -# define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) -# define PB_PACKED_STRUCT_END __pragma(pack(pop)) -# define pb_packed +/* For Microsoft Visual C++ */ +#define PB_PACKED_STRUCT_START __pragma(pack(push, 1)) +#define PB_PACKED_STRUCT_END __pragma(pack(pop)) +#define pb_packed #else - /* Unknown compiler */ -# define PB_PACKED_STRUCT_START -# define PB_PACKED_STRUCT_END -# define pb_packed +/* Unknown compiler */ +#define PB_PACKED_STRUCT_START +#define PB_PACKED_STRUCT_END +#define pb_packed #endif /* Handly macro for suppressing unreferenced-parameter compiler warnings. */ @@ -107,6 +126,19 @@ #define PB_UNUSED(x) (void)(x) #endif +/* Harvard-architecture processors may need special attributes for storing + * field information in program memory. */ +#ifndef PB_PROGMEM +#ifdef __AVR__ +#include +#define PB_PROGMEM PROGMEM +#define PB_PROGMEM_READU32(x) pgm_read_dword(&x) +#else +#define PB_PROGMEM +#define PB_PROGMEM_READU32(x) (x) +#endif +#endif + /* Compile-time assertion, used for checking compatible compilation options. * If this does not work properly on your compiler, use * #define PB_NO_STATIC_ASSERT to disable it. @@ -118,12 +150,23 @@ */ #ifndef PB_NO_STATIC_ASSERT #ifndef PB_STATIC_ASSERT -#define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1]; -#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) -#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +/* C11 standard _Static_assert mechanism */ +#define PB_STATIC_ASSERT(COND, MSG) _Static_assert(COND, #MSG); +#else +/* Classic negative-size-array static assert mechanism */ +#define PB_STATIC_ASSERT(COND, MSG) \ + typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, \ + __COUNTER__)[(COND) ? 1 : -1]; +#define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) \ + PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) +#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) \ + pb_static_assertion_##MSG##_##LINE##_##COUNTER +#endif #endif #else -#define PB_STATIC_ASSERT(COND,MSG) +/* Static asserts disabled by PB_NO_STATIC_ASSERT */ +#define PB_STATIC_ASSERT(COND, MSG) #endif /* Number of required fields to keep track of. */ @@ -135,6 +178,13 @@ #error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64). #endif +#ifdef PB_WITHOUT_64BIT +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Cannot use doubles without 64-bit types */ +#undef PB_CONVERT_DOUBLE_FLOAT +#endif +#endif + /* List of possible field types. These are used in the autogenerated code. * Least-significant 4 bits tell the scalar type * Most-significant 4 bits specify repeated/required/packed etc. @@ -145,72 +195,79 @@ typedef uint_least8_t pb_type_t; /**** Field data types ****/ /* Numeric types */ -#define PB_LTYPE_VARINT 0x00 /* int32, int64, enum, bool */ -#define PB_LTYPE_UVARINT 0x01 /* uint32, uint64 */ -#define PB_LTYPE_SVARINT 0x02 /* sint32, sint64 */ -#define PB_LTYPE_FIXED32 0x03 /* fixed32, sfixed32, float */ -#define PB_LTYPE_FIXED64 0x04 /* fixed64, sfixed64, double */ +#define PB_LTYPE_BOOL 0x00U /* bool */ +#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */ +#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */ +#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */ +#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */ +#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */ /* Marker for last packable field type. */ -#define PB_LTYPE_LAST_PACKABLE 0x04 +#define PB_LTYPE_LAST_PACKABLE 0x05U /* Byte array with pre-allocated buffer. * data_size is the length of the allocated PB_BYTES_ARRAY structure. */ -#define PB_LTYPE_BYTES 0x05 +#define PB_LTYPE_BYTES 0x06U /* String with pre-allocated buffer. * data_size is the maximum length. */ -#define PB_LTYPE_STRING 0x06 +#define PB_LTYPE_STRING 0x07U /* Submessage * submsg_fields is pointer to field descriptions */ -#define PB_LTYPE_SUBMESSAGE 0x07 +#define PB_LTYPE_SUBMESSAGE 0x08U + +/* Submessage with pre-decoding callback + * The pre-decoding callback is stored as pb_callback_t right before pSize. + * submsg_fields is pointer to field descriptions */ +#define PB_LTYPE_SUBMSG_W_CB 0x09U /* Extension pseudo-field * The field contains a pointer to pb_extension_t */ -#define PB_LTYPE_EXTENSION 0x08 +#define PB_LTYPE_EXTENSION 0x0AU /* Byte array with inline, pre-allocated byffer. * data_size is the length of the inline, allocated buffer. * This differs from PB_LTYPE_BYTES by defining the element as * pb_byte_t[data_size] rather than pb_bytes_array_t. */ -#define PB_LTYPE_FIXED_LENGTH_BYTES 0x09 +#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU /* Number of declared LTYPES */ -#define PB_LTYPES_COUNT 0x0A -#define PB_LTYPE_MASK 0x0F +#define PB_LTYPES_COUNT 0x0CU +#define PB_LTYPE_MASK 0x0FU /**** Field repetition rules ****/ -#define PB_HTYPE_REQUIRED 0x00 -#define PB_HTYPE_OPTIONAL 0x10 -#define PB_HTYPE_REPEATED 0x20 -#define PB_HTYPE_ONEOF 0x30 -#define PB_HTYPE_MASK 0x30 +#define PB_HTYPE_REQUIRED 0x00U +#define PB_HTYPE_OPTIONAL 0x10U +#define PB_HTYPE_SINGULAR 0x10U +#define PB_HTYPE_REPEATED 0x20U +#define PB_HTYPE_FIXARRAY 0x20U +#define PB_HTYPE_ONEOF 0x30U +#define PB_HTYPE_MASK 0x30U /**** Field allocation types ****/ - -#define PB_ATYPE_STATIC 0x00 -#define PB_ATYPE_POINTER 0x80 -#define PB_ATYPE_CALLBACK 0x40 -#define PB_ATYPE_MASK 0xC0 -#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK) -#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK) -#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK) +#define PB_ATYPE_STATIC 0x00U +#define PB_ATYPE_POINTER 0x80U +#define PB_ATYPE_CALLBACK 0x40U +#define PB_ATYPE_MASK 0xC0U + +#define PB_ATYPE(x) ((x)&PB_ATYPE_MASK) +#define PB_HTYPE(x) ((x)&PB_HTYPE_MASK) +#define PB_LTYPE(x) ((x)&PB_LTYPE_MASK) +#define PB_LTYPE_IS_SUBMSG(x) \ + (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB) /* Data type used for storing sizes of struct fields * and array counts. */ #if defined(PB_FIELD_32BIT) - typedef uint32_t pb_size_t; - typedef int32_t pb_ssize_t; -#elif defined(PB_FIELD_16BIT) - typedef uint_least16_t pb_size_t; - typedef int_least16_t pb_ssize_t; +typedef uint32_t pb_size_t; +typedef int32_t pb_ssize_t; #else - typedef uint_least8_t pb_size_t; - typedef int_least8_t pb_ssize_t; +typedef uint_least16_t pb_size_t; +typedef int_least16_t pb_ssize_t; #endif #define PB_SIZE_MAX ((pb_size_t)-1) @@ -220,31 +277,55 @@ typedef uint_least8_t pb_type_t; */ typedef uint_least8_t pb_byte_t; +/* Forward declaration of struct types */ +typedef struct pb_istream_s pb_istream_t; +typedef struct pb_ostream_s pb_ostream_t; +typedef struct pb_field_iter_s pb_field_iter_t; + /* This structure is used in auto-generated constants * to specify struct fields. - * You can change field sizes if you need structures - * larger than 256 bytes or field tags larger than 256. - * The compiler should complain if your .proto has such - * structures. Fix that by defining PB_FIELD_16BIT or - * PB_FIELD_32BIT. */ PB_PACKED_STRUCT_START -typedef struct pb_field_s pb_field_t; -struct pb_field_s { - pb_size_t tag; - pb_type_t type; - pb_size_t data_offset; /* Offset of field data, relative to previous field. */ - pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */ - pb_size_t data_size; /* Data size in bytes for a single item */ - pb_size_t array_size; /* Maximum number of entries in array */ - - /* Field definitions for submessage - * OR default value for all other non-array, non-callback types - * If null, then field will zeroed. */ - const void *ptr; +typedef struct pb_msgdesc_s pb_msgdesc_t; +struct pb_msgdesc_s { + pb_size_t field_count; + const uint32_t *field_info; + const pb_msgdesc_t *const *submsg_info; + const pb_byte_t *default_value; + + bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, + const pb_field_iter_t *field); } pb_packed; PB_PACKED_STRUCT_END +/* Iterator for message descriptor */ +struct pb_field_iter_s { + const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */ + void *message; /* Pointer to start of the structure */ + + pb_size_t index; /* Index of the field */ + pb_size_t field_info_index; /* Index to descriptor->field_info array */ + pb_size_t + required_field_index; /* Index that counts only the required fields */ + pb_size_t submessage_index; /* Index that counts only submessages */ + + pb_size_t tag; /* Tag of current field */ + pb_size_t data_size; /* sizeof() of a single item */ + pb_size_t array_size; /* Number of array entries */ + pb_type_t type; /* Type of current field */ + + void *pField; /* Pointer to current field in struct */ + void *pData; /* Pointer to current data contents. Different than pField for + arrays and pointers. */ + void *pSize; /* Pointer to count/has field */ + + const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field + descriptor for the submessage. */ +}; + +/* For compatibility with legacy code */ +typedef pb_field_iter_t pb_field_t; + /* Make sure that the standard integer types are of the expected sizes. * Otherwise fixed32/fixed64 fields can break. * @@ -260,12 +341,17 @@ PB_STATIC_ASSERT(sizeof(uint64_t) == 2 * sizeof(uint32_t), UINT64_T_WRONG_SIZE) * It has the number of bytes in the beginning, and after that an array. * Note that actual structs used will have a different length of bytes array. */ -#define PB_BYTES_ARRAY_T(n) struct { pb_size_t size; pb_byte_t bytes[n]; } -#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) ((size_t)n + offsetof(pb_bytes_array_t, bytes)) +#define PB_BYTES_ARRAY_T(n) \ + struct { \ + pb_size_t size; \ + pb_byte_t bytes[n]; \ + } +#define PB_BYTES_ARRAY_T_ALLOCSIZE(n) \ + ((size_t)n + offsetof(pb_bytes_array_t, bytes)) struct pb_bytes_array_s { - pb_size_t size; - pb_byte_t bytes[1]; + pb_size_t size; + pb_byte_t bytes[1]; }; typedef struct pb_bytes_array_s pb_bytes_array_t; @@ -287,34 +373,31 @@ typedef struct pb_bytes_array_s pb_bytes_array_t; * * The callback can be null if you want to skip a field. */ -typedef struct pb_istream_s pb_istream_t; -typedef struct pb_ostream_s pb_ostream_t; typedef struct pb_callback_s pb_callback_t; struct pb_callback_s { -#ifdef PB_OLD_CALLBACK_STYLE - /* Deprecated since nanopb-0.2.1 */ - union { - bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg); - bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg); - } funcs; -#else - /* New function signature, which allows modifying arg contents in callback. */ - union { - bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); - bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg); - } funcs; -#endif - - /* Free arg for use by callback */ - void *arg; + /* Callback functions receive a pointer to the arg field. + * You can access the value of the field as *arg, and modify it if needed. + */ + union { + bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg); + bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, + void *const *arg); + } funcs; + + /* Free arg for use by callback */ + void *arg; }; +extern bool pb_default_field_callback(pb_istream_t *istream, + pb_ostream_t *ostream, + const pb_field_t *field); + /* Wire types. Library user needs these only in encoder callbacks. */ typedef enum { - PB_WT_VARINT = 0, - PB_WT_64BIT = 1, - PB_WT_STRING = 2, - PB_WT_32BIT = 5 + PB_WT_VARINT = 0, + PB_WT_64BIT = 1, + PB_WT_STRING = 2, + PB_WT_32BIT = 5 } pb_wire_type_t; /* Structure for defining the handling of unknown/extension fields. @@ -326,240 +409,500 @@ typedef enum { typedef struct pb_extension_type_s pb_extension_type_t; typedef struct pb_extension_s pb_extension_t; struct pb_extension_type_s { - /* Called for each unknown field in the message. - * If you handle the field, read off all of its data and return true. - * If you do not handle the field, do not read anything and return true. - * If you run into an error, return false. - * Set to NULL for default handler. - */ - bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, - uint32_t tag, pb_wire_type_t wire_type); - - /* Called once after all regular fields have been encoded. - * If you have something to write, do so and return true. - * If you do not have anything to write, just return true. - * If you run into an error, return false. - * Set to NULL for default handler. - */ - bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); - - /* Free field for use by the callback. */ - const void *arg; + /* Called for each unknown field in the message. + * If you handle the field, read off all of its data and return true. + * If you do not handle the field, do not read anything and return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*decode)(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, + pb_wire_type_t wire_type); + + /* Called once after all regular fields have been encoded. + * If you have something to write, do so and return true. + * If you do not have anything to write, just return true. + * If you run into an error, return false. + * Set to NULL for default handler. + */ + bool (*encode)(pb_ostream_t *stream, const pb_extension_t *extension); + + /* Free field for use by the callback. */ + const void *arg; }; struct pb_extension_s { - /* Type describing the extension field. Usually you'll initialize - * this to a pointer to the automatically generated structure. */ - const pb_extension_type_t *type; - - /* Destination for the decoded data. This must match the datatype - * of the extension field. */ - void *dest; - - /* Pointer to the next extension handler, or NULL. - * If this extension does not match a field, the next handler is - * automatically called. */ - pb_extension_t *next; - - /* The decoder sets this to true if the extension was found. - * Ignored for encoding. */ - bool found; + /* Type describing the extension field. Usually you'll initialize + * this to a pointer to the automatically generated structure. */ + const pb_extension_type_t *type; + + /* Destination for the decoded data. This must match the datatype + * of the extension field. */ + void *dest; + + /* Pointer to the next extension handler, or NULL. + * If this extension does not match a field, the next handler is + * automatically called. */ + pb_extension_t *next; + + /* The decoder sets this to true if the extension was found. + * Ignored for encoding. */ + bool found; }; +#define pb_extension_init_zero \ + { NULL, NULL, NULL, false } + /* Memory allocation functions to use. You can define pb_realloc and * pb_free to custom functions if you want. */ #ifdef PB_ENABLE_MALLOC -# ifndef pb_realloc -# define pb_realloc(ptr, size) realloc(ptr, size) -# endif -# ifndef pb_free -# define pb_free(ptr) free(ptr) -# endif +#ifndef pb_realloc +#define pb_realloc(ptr, size) realloc(ptr, size) +#endif +#ifndef pb_free +#define pb_free(ptr) free(ptr) +#endif #endif /* This is used to inform about need to regenerate .pb.h/.pb.c files. */ -#define PB_PROTO_HEADER_VERSION 30 +#define PB_PROTO_HEADER_VERSION 40 /* These macros are used to declare pb_field_t's in the constant array. */ /* Size of a structure member, in bytes. */ -#define pb_membersize(st, m) (sizeof ((st*)0)->m) +#define pb_membersize(st, m) (sizeof((st *)0)->m) /* Number of entries in an array. */ #define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0])) /* Delta from start of one member to the start of another member. */ #define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2)) -/* Marks the end of the field list */ -#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0} - -/* Macros for filling in the data_offset field */ -/* data_offset for first field in a message */ -#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1)) -/* data_offset for subsequent fields */ -#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2)) -/* data offset for subsequent fields inside an union (oneof) */ -#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX) -/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */ -#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \ - ? PB_DATAOFFSET_FIRST(st, m1, m2) \ - : PB_DATAOFFSET_OTHER(st, m1, m2)) - -/* Required fields are the simplest. They just have delta (padding) from - * previous field end, and the size of the field. Pointer is used for - * submessages and default values. + +/* Force expansion of macro value */ +#define PB_EXPAND(x) x + +/* Binding of a message field set into a specific structure */ +#define PB_BIND(msgname, structname, width) \ + const uint32_t structname##_field_info[] PB_PROGMEM = { \ + msgname##_FIELDLIST(PB_GEN_FIELD_INFO_##width, structname) 0}; \ + const pb_msgdesc_t *const structname##_submsg_info[] = { \ + msgname##_FIELDLIST(PB_GEN_SUBMSG_INFO, structname) NULL}; \ + const pb_msgdesc_t structname##_msg = { \ + 0 msgname##_FIELDLIST(PB_GEN_FIELD_COUNT, structname), \ + structname##_field_info, \ + structname##_submsg_info, \ + msgname##_DEFAULT, \ + msgname##_CALLBACK, \ + }; \ + msgname##_FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_##width, structname) + +#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1 + +#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(1, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(2, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(4, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \ + PB_GEN_FIELD_INFO(8, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_GEN_FIELD_INFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), \ + structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_AUTO2(width, structname, atype, htype, ltype, \ + fieldname, tag) \ + PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_FIELDINFO_##width( \ + tag, PB_ATYPE_##atype | PB_HTYPE_##htype | PB_LTYPE_MAP_##ltype, \ + PB_DATA_OFFSET_##atype(htype, structname, fieldname), \ + PB_DATA_SIZE_##atype(htype, structname, fieldname), \ + PB_SIZE_OFFSET_##atype(htype, structname, fieldname), \ + PB_ARRAY_SIZE_##atype(htype, structname, fieldname)) + +#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_GEN_FIELD_INFO_ASSERT(1, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_GEN_FIELD_INFO_ASSERT(2, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_GEN_FIELD_INFO_ASSERT(4, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, \ + tag) \ + PB_GEN_FIELD_INFO_ASSERT(8, structname, atype, htype, ltype, fieldname, tag) + +#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, \ + fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), \ + structname, atype, htype, ltype, fieldname, \ + tag) + +#define PB_GEN_FIELD_INFO_ASSERT_AUTO2(width, structname, atype, htype, ltype, \ + fieldname, tag) \ + PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, \ + tag) + +#define PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, \ + fieldname, tag) \ + PB_FIELDINFO_ASSERT_##width( \ + tag, PB_ATYPE_##atype | PB_HTYPE_##htype | PB_LTYPE_MAP_##ltype, \ + PB_DATA_OFFSET_##atype(htype, structname, fieldname), \ + PB_DATA_SIZE_##atype(htype, structname, fieldname), \ + PB_SIZE_OFFSET_##atype(htype, structname, fieldname), \ + PB_ARRAY_SIZE_##atype(htype, structname, fieldname)) + +#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) \ + PB_DATA_OFFSET_##htype(structname, fieldname) +#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) \ + PB_DATA_OFFSET_##htype(structname, fieldname) +#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) \ + PB_DATA_OFFSET_##htype(structname, fieldname) +#define PB_DATA_OFFSET_REQUIRED(structname, fieldname) \ + offsetof(structname, fieldname) +#define PB_DATA_OFFSET_SINGULAR(structname, fieldname) \ + offsetof(structname, fieldname) +#define PB_DATA_OFFSET_ONEOF(structname, fieldname) \ + offsetof(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_OFFSET_OPTIONAL(structname, fieldname) \ + offsetof(structname, fieldname) +#define PB_DATA_OFFSET_REPEATED(structname, fieldname) \ + offsetof(structname, fieldname) +#define PB_DATA_OFFSET_FIXARRAY(structname, fieldname) \ + offsetof(structname, fieldname) + +#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) \ + PB_SIZE_OFFSET_##htype(structname, fieldname) +#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) \ + PB_SIZE_OFFSET_PTR_##htype(structname, fieldname) +#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) \ + PB_SIZE_OFFSET_CB_##htype(structname, fieldname) +#define PB_SIZE_OFFSET_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_ONEOF(structname, fieldname) \ + PB_SIZE_OFFSET_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), \ + PB_ONEOF_NAME(UNION, fieldname)) +#define PB_SIZE_OFFSET_ONEOF2(structname, fullname, unionname) \ + PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) +#define PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) \ + pb_delta(structname, fullname, which_##unionname) +#define PB_SIZE_OFFSET_OPTIONAL(structname, fieldname) \ + pb_delta(structname, fieldname, has_##fieldname) +#define PB_SIZE_OFFSET_REPEATED(structname, fieldname) \ + pb_delta(structname, fieldname, fieldname##_count) +#define PB_SIZE_OFFSET_FIXARRAY(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_ONEOF(structname, fieldname) \ + PB_SIZE_OFFSET_ONEOF(structname, fieldname) +#define PB_SIZE_OFFSET_PTR_OPTIONAL(structname, fieldname) 0 +#define PB_SIZE_OFFSET_PTR_REPEATED(structname, fieldname) \ + PB_SIZE_OFFSET_REPEATED(structname, fieldname) +#define PB_SIZE_OFFSET_PTR_FIXARRAY(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_REQUIRED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_SINGULAR(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_ONEOF(structname, fieldname) \ + PB_SIZE_OFFSET_ONEOF(structname, fieldname) +#define PB_SIZE_OFFSET_CB_OPTIONAL(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_REPEATED(structname, fieldname) 0 +#define PB_SIZE_OFFSET_CB_FIXARRAY(structname, fieldname) 0 + +#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) \ + PB_ARRAY_SIZE_##htype(structname, fieldname) +#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) 1 +#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1 +#define PB_ARRAY_SIZE_REQUIRED(structname, fieldname) 1 +#define PB_ARRAY_SIZE_SINGULAR(structname, fieldname) 1 +#define PB_ARRAY_SIZE_OPTIONAL(structname, fieldname) 1 +#define PB_ARRAY_SIZE_ONEOF(structname, fieldname) 1 +#define PB_ARRAY_SIZE_REPEATED(structname, fieldname) \ + pb_arraysize(structname, fieldname) +#define PB_ARRAY_SIZE_FIXARRAY(structname, fieldname) \ + pb_arraysize(structname, fieldname) + +#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) \ + PB_DATA_SIZE_##htype(structname, fieldname) +#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) \ + PB_DATA_SIZE_PTR_##htype(structname, fieldname) +#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) \ + PB_DATA_SIZE_CB_##htype(structname, fieldname) +#define PB_DATA_SIZE_REQUIRED(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_SINGULAR(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_OPTIONAL(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_ONEOF(structname, fieldname) \ + pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_SIZE_REPEATED(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_FIXARRAY(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_REQUIRED(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_SINGULAR(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_OPTIONAL(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_ONEOF(structname, fieldname) \ + pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0]) +#define PB_DATA_SIZE_PTR_REPEATED(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_PTR_FIXARRAY(structname, fieldname) \ + pb_membersize(structname, fieldname[0]) +#define PB_DATA_SIZE_CB_REQUIRED(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_SINGULAR(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_OPTIONAL(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_ONEOF(structname, fieldname) \ + pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)) +#define PB_DATA_SIZE_CB_REPEATED(structname, fieldname) \ + pb_membersize(structname, fieldname) +#define PB_DATA_SIZE_CB_FIXARRAY(structname, fieldname) \ + pb_membersize(structname, fieldname) + +#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_##type tuple) +#define PB_ONEOF_NAME_UNION(unionname, membername, fullname) unionname +#define PB_ONEOF_NAME_MEMBER(unionname, membername, fullname) membername +#define PB_ONEOF_NAME_FULL(unionname, membername, fullname) fullname + +#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \ + PB_SUBMSG_INFO_##htype(ltype, structname, fieldname) + +#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_##ltype(structname##_##fieldname##_MSGTYPE) +#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_##ltype(structname##_##fieldname##_MSGTYPE) +#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_##ltype(structname##_##fieldname##_MSGTYPE) +#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), \ + PB_ONEOF_NAME(MEMBER, fieldname)) +#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) \ + PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) +#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) \ + PB_SUBMSG_INFO_##ltype(structname##_##unionname##_##membername##_MSGTYPE) +#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_##ltype(structname##_##fieldname##_MSGTYPE) +#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) \ + PB_SUBMSG_INFO_##ltype(structname##_##fieldname##_MSGTYPE) +#define PB_SUBMSG_INFO_BOOL(t) +#define PB_SUBMSG_INFO_BYTES(t) +#define PB_SUBMSG_INFO_DOUBLE(t) +#define PB_SUBMSG_INFO_ENUM(t) +#define PB_SUBMSG_INFO_UENUM(t) +#define PB_SUBMSG_INFO_FIXED32(t) +#define PB_SUBMSG_INFO_FIXED64(t) +#define PB_SUBMSG_INFO_FLOAT(t) +#define PB_SUBMSG_INFO_INT32(t) +#define PB_SUBMSG_INFO_INT64(t) +#define PB_SUBMSG_INFO_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SUBMSG_INFO_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t) +#define PB_SUBMSG_INFO_SFIXED32(t) +#define PB_SUBMSG_INFO_SFIXED64(t) +#define PB_SUBMSG_INFO_SINT32(t) +#define PB_SUBMSG_INFO_SINT64(t) +#define PB_SUBMSG_INFO_STRING(t) +#define PB_SUBMSG_INFO_UINT32(t) +#define PB_SUBMSG_INFO_UINT64(t) +#define PB_SUBMSG_INFO_EXTENSION(t) +#define PB_SUBMSG_INFO_FIXED_LENGTH_BYTES(t) +#define PB_SUBMSG_DESCRIPTOR(t) &(t##_msg), + +/* The field descriptors use a variable width format, with width of either + * 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always + * encode the descriptor size, 6 lowest bits of field tag number, and 8 bits + * of the field type. + * + * Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 + * words. + * + * Formats, listed starting with the least significant bit of the first word. + * 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit + * size_offset] [4-bit data_size] + * + * 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit + * size_offset] [16-bit data_offset] [12-bit data_size] [4-bit tag>>6] + * + * 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * + * 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved] + * [8-bit size_offset] [24-bit tag>>6] + * [32-bit data_offset] + * [32-bit data_size] + * [32-bit array_size] + * [32-bit reserved] + * [32-bit reserved] + * [32-bit reserved] */ -#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -/* Optional fields add the delta to the has_ variable. */ -#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ - fd, \ - pb_delta(st, has_ ## m, m), \ - pb_membersize(st, m), 0, ptr} - -#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -/* Repeated fields have a _count field and also the maximum number of entries. */ -#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \ - fd, \ - pb_delta(st, m ## _count, m), \ - pb_membersize(st, m[0]), \ - pb_arraysize(st, m), ptr} - -/* Allocated fields carry the size of the actual data, not the pointer */ -#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \ - fd, 0, pb_membersize(st, m[0]), 0, ptr} - -/* Optional fields don't need a has_ variable, as information would be redundant */ -#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ - fd, 0, pb_membersize(st, m[0]), 0, ptr} - -/* Same as optional fields*/ -#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \ - fd, 0, pb_membersize(st, m[0]), 0, ptr} - -/* Repeated fields have a _count field and a pointer to array of pointers */ -#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \ - fd, pb_delta(st, m ## _count, m), \ - pb_membersize(st, m[0]), 0, ptr} - -/* Callbacks are much like required fields except with special datatype. */ -#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \ - fd, 0, pb_membersize(st, m), 0, ptr} - -/* Optional extensions don't have the has_ field, as that would be redundant. - * Furthermore, the combination of OPTIONAL without has_ field is used - * for indicating proto3 style fields. Extensions exist in proto2 mode only, - * so they should be encoded according to proto2 rules. To avoid the conflict, - * extensions are marked as REQUIRED instead. + +#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + (0 | (((tag) << 2) & 0xFF) | ((type) << 8) | \ + (((uint32_t)(data_offset)&0xFF) << 16) | \ + (((uint32_t)(size_offset)&0x0F) << 24) | \ + (((uint32_t)(data_size)&0x0F) << 28)), + +#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + (1 | (((tag) << 2) & 0xFF) | ((type) << 8) | \ + (((uint32_t)(array_size)&0xFFF) << 16) | \ + (((uint32_t)(size_offset)&0x0F) << 28)), \ + (((uint32_t)(data_offset)&0xFFFF) | \ + (((uint32_t)(data_size)&0xFFF) << 16) | \ + (((uint32_t)(tag)&0x2c0) << 22)), + +#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + (2 | (((tag) << 2) & 0xFF) | ((type) << 8) | \ + (((uint32_t)(array_size)&0xFFFF) << 16)), \ + ((uint32_t)(int8_t)(size_offset) | \ + (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), + +#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + (3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \ + ((uint32_t)(int8_t)(size_offset) | \ + (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \ + (data_offset), (data_size), (array_size) + +/* These assertions verify that the field information fits in the allocated + * space. The generator tries to automatically determine the correct width that + * can fit all data associated with a message. These asserts will fail only if + * there has been a problem in the automatic logic - this may be worth reporting + * as a bug. As a workaround, you can increase the descriptor width by defining + * PB_FIELDINFO_WIDTH or by setting descriptorsize option in .options file. + */ +#define PB_FITS(value, bits) ((uint32_t)(value) < ((uint32_t)1 << bits)) +#define PB_FIELDINFO_ASSERT_1(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 6) && PB_FITS(data_offset, 8) && \ + PB_FITS(size_offset, 4) && PB_FITS(data_size, 4) && \ + PB_FITS(array_size, 1), \ + FIELDINFO_DOES_NOT_FIT_width1_field##tag) + +#define PB_FIELDINFO_ASSERT_2(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 10) && PB_FITS(data_offset, 16) && \ + PB_FITS(size_offset, 4) && PB_FITS(data_size, 12) && \ + PB_FITS(array_size, 12), \ + FIELDINFO_DOES_NOT_FIT_width2_field##tag) + +#ifndef PB_FIELD_32BIT +/* Maximum field sizes are still 16-bit if pb_size_t is 16-bit */ +#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 16) && PB_FITS(data_offset, 16) && \ + PB_FITS((int8_t)size_offset, 8) && \ + PB_FITS(data_size, 16) && PB_FITS(array_size, 16), \ + FIELDINFO_DOES_NOT_FIT_width4_field##tag) + +#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 16) && PB_FITS(data_offset, 16) && \ + PB_FITS((int8_t)size_offset, 8) && \ + PB_FITS(data_size, 16) && PB_FITS(array_size, 16), \ + FIELDINFO_DOES_NOT_FIT_width8_field##tag) +#else +/* Up to 32-bit fields supported. + * Note that the checks are against 31 bits to avoid compiler warnings about + * shift wider than type in the test. I expect that there is no reasonable use + * for >2GB messages with nanopb anyway. */ -#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \ - 0, \ - 0, \ - pb_membersize(st, m), 0, ptr} +#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 30) && PB_FITS(data_offset, 31) && \ + PB_FITS((int8_t)size_offset, 8) && \ + PB_FITS(data_size, 31) && PB_FITS(array_size, 16), \ + FIELDINFO_DOES_NOT_FIT_width4_field##tag) + +#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, \ + array_size) \ + PB_STATIC_ASSERT(PB_FITS(tag, 30) && PB_FITS(data_offset, 31) && \ + PB_FITS((int8_t)size_offset, 8) && \ + PB_FITS(data_size, 31) && PB_FITS(array_size, 31), \ + FIELDINFO_DOES_NOT_FIT_width8_field##tag) +#endif -#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \ - PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) +/* Automatic picking of FIELDINFO width: + * Uses width 1 when possible, otherwise resorts to width 2. + */ -#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \ - PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) +#ifndef PB_FIELDINFO_WIDTH +#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) \ + PB_FIELDINFO_WIDTH_##atype(htype, ltype) +#define PB_FIELDINFO_WIDTH_STATIC(htype, ltype) \ + PB_FIELDINFO_WIDTH_##htype(ltype) +#define PB_FIELDINFO_WIDTH_POINTER(htype, ltype) \ + PB_FIELDINFO_WIDTH_##htype(ltype) +#define PB_FIELDINFO_WIDTH_CALLBACK(htype, ltype) 2 +#define PB_FIELDINFO_WIDTH_REQUIRED(ltype) PB_FIELDINFO_WIDTH_##ltype +#define PB_FIELDINFO_WIDTH_SINGULAR(ltype) PB_FIELDINFO_WIDTH_##ltype +#define PB_FIELDINFO_WIDTH_OPTIONAL(ltype) PB_FIELDINFO_WIDTH_##ltype +#define PB_FIELDINFO_WIDTH_ONEOF(ltype) PB_FIELDINFO_WIDTH_##ltype +#define PB_FIELDINFO_WIDTH_REPEATED(ltype) 2 +#define PB_FIELDINFO_WIDTH_FIXARRAY(ltype) 2 +#define PB_FIELDINFO_WIDTH_BOOL 1 +#define PB_FIELDINFO_WIDTH_BYTES 2 +#define PB_FIELDINFO_WIDTH_DOUBLE 1 +#define PB_FIELDINFO_WIDTH_ENUM 1 +#define PB_FIELDINFO_WIDTH_UENUM 1 +#define PB_FIELDINFO_WIDTH_FIXED32 1 +#define PB_FIELDINFO_WIDTH_FIXED64 1 +#define PB_FIELDINFO_WIDTH_FLOAT 1 +#define PB_FIELDINFO_WIDTH_INT32 1 +#define PB_FIELDINFO_WIDTH_INT64 1 +#define PB_FIELDINFO_WIDTH_MESSAGE 2 +#define PB_FIELDINFO_WIDTH_SFIXED32 1 +#define PB_FIELDINFO_WIDTH_SFIXED64 1 +#define PB_FIELDINFO_WIDTH_SINT32 1 +#define PB_FIELDINFO_WIDTH_SINT64 1 +#define PB_FIELDINFO_WIDTH_STRING 2 +#define PB_FIELDINFO_WIDTH_UINT32 1 +#define PB_FIELDINFO_WIDTH_UINT64 1 +#define PB_FIELDINFO_WIDTH_EXTENSION 1 +#define PB_FIELDINFO_WIDTH_FIXED_LENGTH_BYTES 2 +#else +#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FIELDINFO_WIDTH +#endif /* The mapping from protobuf types to LTYPEs is done using these macros. */ -#define PB_LTYPE_MAP_BOOL PB_LTYPE_VARINT -#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES -#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 -#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT -#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT -#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 -#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 -#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 -#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT -#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT -#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE -#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 -#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 -#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT -#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT -#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING -#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT -#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT -#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION +#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL +#define PB_LTYPE_MAP_BYTES PB_LTYPE_BYTES +#define PB_LTYPE_MAP_DOUBLE PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_ENUM PB_LTYPE_VARINT +#define PB_LTYPE_MAP_UENUM PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_FIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_FIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_FLOAT PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT +#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE +#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB +#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32 +#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64 +#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_SINT64 PB_LTYPE_SVARINT +#define PB_LTYPE_MAP_STRING PB_LTYPE_STRING +#define PB_LTYPE_MAP_UINT32 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_UINT64 PB_LTYPE_UVARINT +#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION #define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES -/* This is the actual macro used in field descriptions. - * It takes these arguments: - * - Field tag number - * - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64, - * FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64 - * SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION - * - Field rules: REQUIRED, OPTIONAL or REPEATED - * - Allocation: STATIC, CALLBACK or POINTER - * - Placement: FIRST or OTHER, depending on if this is the first field in structure. - * - Message name - * - Field name - * - Previous field name (or field name again for first field) - * - Pointer to default value or submsg fields. - */ - -#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ - PB_ ## rules ## _ ## allocation(tag, message, field, \ - PB_DATAOFFSET_ ## placement(message, field, prevfield), \ - PB_LTYPE_MAP_ ## type, ptr) - -/* Field description for oneof fields. This requires taking into account the - * union name also, that's why a separate set of macros is needed. - */ -#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ - fd, pb_delta(st, which_ ## u, u.m), \ - pb_membersize(st, u.m), 0, ptr} - -#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ - fd, pb_delta(st, which_ ## u, u.m), \ - pb_membersize(st, u.m[0]), 0, ptr} - -#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ - PB_ONEOF_ ## allocation(union_name, tag, message, field, \ - PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \ - PB_LTYPE_MAP_ ## type, ptr) - -#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \ - fd, pb_delta(st, which_ ## u, m), \ - pb_membersize(st, m), 0, ptr} - -#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \ - {tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \ - fd, pb_delta(st, which_ ## u, m), \ - pb_membersize(st, m[0]), 0, ptr} - -#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \ - PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \ - PB_DATAOFFSET_ ## placement(message, field, prevfield), \ - PB_LTYPE_MAP_ ## type, ptr) - /* These macros are used for giving out error messages. * They are mostly a debugging aid; the main error information * is the true/false return value from functions. @@ -571,22 +914,39 @@ struct pb_extension_s { * PB_GET_ERROR() always returns a pointer to a string. * PB_RETURN_ERROR() sets the error and returns false from current * function. - * G_depth is a global that should be initialized to 0 when - * creating an input stream. It helps tracking the level of the - * call stack when instrumentation is enabled - * (set `INTRUMENT_FUNCTION += -finstrument-functions` in your - * Makfile to do so) */ -extern int G_depth; - #ifdef PB_NO_ERRMSG #define PB_SET_ERROR(stream, msg) PB_UNUSED(stream) #define PB_GET_ERROR(stream) "(errmsg disabled)" #else -#define PB_SET_ERROR(stream, msg) (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) +#define PB_SET_ERROR(stream, msg) \ + (stream->errmsg = (stream)->errmsg ? (stream)->errmsg : (msg)) #define PB_GET_ERROR(stream) ((stream)->errmsg ? (stream)->errmsg : "(none)") #endif #define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#ifdef __cplusplus +#if __cplusplus >= 201103L +#define PB_CONSTEXPR constexpr +#else // __cplusplus >= 201103L +#define PB_CONSTEXPR +#endif // __cplusplus >= 201103L + +#if __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR inline constexpr +#else // __cplusplus >= 201703L +#define PB_INLINE_CONSTEXPR PB_CONSTEXPR +#endif // __cplusplus >= 201703L + +namespace nanopb { +// Each type will be partially specialized by the generator. +template struct MessageDescriptor; +} // namespace nanopb +#endif /* __cplusplus */ + #endif diff --git a/src/nanopb/pb_common.c b/src/nanopb/pb_common.c index adfa747a..9b7baaac 100644 --- a/src/nanopb/pb_common.c +++ b/src/nanopb/pb_common.c @@ -3,108 +3,274 @@ * 2014 Petteri Aimonen */ -#include "pb_common.h" #include "os.h" +#include "pb_common.h" +static bool load_descriptor_values(pb_field_iter_t *iter) { + uint32_t word0; + uint32_t data_offset; + uint8_t format; + int8_t size_offset; -bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct) -{ - iter->start = (const pb_field_t *)PIC(fields); - iter->pos = (const pb_field_t *)PIC(fields); - iter->required_field_index = 0; - iter->dest_struct = dest_struct; - iter->pData = (char*)dest_struct + iter->pos->data_offset; - iter->pSize = (char*)iter->pData + iter->pos->size_offset; - return (iter->pos->tag != 0); + if (iter->index >= iter->descriptor->field_count) + return false; + + word0 = PB_PROGMEM_READU32( + ((uint32_t *)PIC(((pb_msgdesc_t *)PIC(iter->descriptor)) + ->field_info))[iter->field_info_index]); + format = word0 & 3; + iter->tag = (pb_size_t)((word0 >> 2) & 0x3F); + iter->type = (pb_type_t)((word0 >> 8) & 0xFF); + + if (format == 0) { + /* 1-word format */ + iter->array_size = 1; + size_offset = (int8_t)((word0 >> 24) & 0x0F); + data_offset = (word0 >> 16) & 0xFF; + iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F); + } else if (format == 1) { + /* 2-word format */ + uint32_t word1 = PB_PROGMEM_READU32( + ((uint32_t *)PIC(((pb_msgdesc_t *)PIC(iter->descriptor)) + ->field_info))[iter->field_info_index + 1]); + + iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF); + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 28) << 6)); + size_offset = (int8_t)((word0 >> 28) & 0x0F); + data_offset = word1 & 0xFFFF; + iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF); + } else if (format == 2) { + /* 4-word format */ + uint32_t word1 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 3]); + + iter->array_size = (pb_size_t)(word0 >> 16); + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); + size_offset = (int8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + } else { + /* 8-word format */ + uint32_t word1 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 1]); + uint32_t word2 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 2]); + uint32_t word3 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 3]); + uint32_t word4 = PB_PROGMEM_READU32( + iter->descriptor->field_info[iter->field_info_index + 4]); + + iter->array_size = (pb_size_t)word4; + iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6)); + size_offset = (int8_t)(word1 & 0xFF); + data_offset = word2; + iter->data_size = (pb_size_t)word3; + } + + iter->pField = (char *)iter->message + data_offset; + + if (size_offset) { + iter->pSize = (char *)iter->pField - size_offset; + } else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED && + (PB_ATYPE(iter->type) == PB_ATYPE_STATIC || + PB_ATYPE(iter->type) == PB_ATYPE_POINTER)) { + /* Fixed count array */ + iter->pSize = &iter->array_size; + } else { + iter->pSize = NULL; + } + + if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL) { + iter->pData = *(void **)iter->pField; + } else { + iter->pData = iter->pField; + } + + if (PB_LTYPE_IS_SUBMSG(iter->type)) { + iter->submsg_desc = ((const pb_msgdesc_t *const *)PIC( + ((pb_msgdesc_t *)PIC(iter->descriptor)) + ->submsg_info))[iter->submessage_index]; + } else { + iter->submsg_desc = NULL; + } + + return true; } -bool pb_field_iter_next(pb_field_iter_t *iter) -{ - const pb_field_t *prev_field = ((const pb_field_t *)PIC(iter->pos)); +static void advance_iterator(pb_field_iter_t *iter) { + iter->index++; - if (prev_field->tag == 0) - { - /* Handle empty message types, where the first field is already the terminator. - * In other cases, the iter->pos never points to the terminator. */ - return false; - } - - iter->pos = ((const pb_field_t *)PIC(iter->pos))+1; - - if (((const pb_field_t *)PIC(iter->pos))->tag == 0) - { - /* Wrapped back to beginning, reinitialize */ - (void)pb_field_iter_begin(iter, ((const pb_field_t *)PIC(iter->start)), iter->dest_struct); - return false; + if (iter->index >= iter->descriptor->field_count) { + /* Restart */ + iter->index = 0; + iter->field_info_index = 0; + iter->submessage_index = 0; + iter->required_field_index = 0; + } else { + /* Increment indexes based on previous field type. + * All field info formats have the following fields: + * - lowest 2 bits tell the amount of words in the descriptor (2^n words) + * - bits 2..7 give the lowest bits of tag number. + * - bits 8..15 give the field type. + */ + uint32_t prev_descriptor = PB_PROGMEM_READU32( + ((uint32_t *)PIC(((pb_msgdesc_t *)PIC(iter->descriptor)) + ->field_info))[iter->field_info_index]); + + pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF; + pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3)); + + iter->field_info_index = + (pb_size_t)(iter->field_info_index + descriptor_len); + + if (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED) { + iter->required_field_index++; } - else - { - /* Increment the pointers based on previous field size */ - size_t prev_size = prev_field->data_size; - - if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF && - PB_HTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_HTYPE_ONEOF && - ((const pb_field_t *)PIC(iter->pos))->data_offset == PB_SIZE_MAX) - { - /* Don't advance pointers inside unions */ - return true; - } - else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC && - PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED) - { - /* In static arrays, the data_size tells the size of a single entry and - * array_size is the number of entries */ - prev_size *= prev_field->array_size; - } - else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER) - { - /* Pointer fields always have a constant size in the main structure. - * The data_size only applies to the dynamically allocated area. */ - prev_size = sizeof(void*); - } - if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED) - { - /* Count the required fields, in order to check their presence in the - * decoder. */ - iter->required_field_index++; - } - - iter->pData = (char*)iter->pData + prev_size + ((const pb_field_t *)PIC(iter->pos))->data_offset; - iter->pSize = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->size_offset; - return true; + if (PB_LTYPE_IS_SUBMSG(prev_type)) { + iter->submessage_index++; } + } +} + +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, + void *message) { + memset(iter, 0, sizeof(*iter)); + + iter->descriptor = PIC(desc); + iter->message = message; + + return load_descriptor_values(iter); +} + +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, + pb_extension_t *extension) { + const pb_msgdesc_t *msg = (const pb_msgdesc_t *)extension->type->arg; + bool status; + + uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]); + if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER) { + /* For pointer extensions, the pointer is stored directly + * in the extension structure. This avoids having an extra + * indirection. */ + status = pb_field_iter_begin(iter, msg, &extension->dest); + } else { + status = pb_field_iter_begin(iter, msg, extension->dest); + } + + iter->pSize = &extension->found; + return status; +} + +bool pb_field_iter_next(pb_field_iter_t *iter) { + advance_iterator(iter); + (void)load_descriptor_values(iter); + return iter->index != 0; } -bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) -{ - const pb_field_t *start = ((const pb_field_t *)PIC(iter->pos)); - +bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag) { + if (iter->tag == tag) { + return true; /* Nothing to do, correct field already. */ + } else { + pb_size_t start = iter->index; + uint32_t fieldinfo; + do { - if (((const pb_field_t *)PIC(iter->pos))->tag == tag && - PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) != PB_LTYPE_EXTENSION) - { - /* Found the wanted field */ - return true; + /* Advance iterator but don't load values yet */ + advance_iterator(iter); + + /* Do fast check for tag number match */ + fieldinfo = PB_PROGMEM_READU32( + ((uint32_t *)PIC(((pb_msgdesc_t *)PIC(iter->descriptor)) + ->field_info))[iter->field_info_index]); + + if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F)) { + /* Good candidate, check further */ + (void)load_descriptor_values(iter); + + if (iter->tag == tag && PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION) { + /* Found it */ + return true; } - - (void)pb_field_iter_next(iter); - } while (((const pb_field_t *)PIC(iter->pos)) != start); - + } + } while (iter->index != start); + /* Searched all the way back to start, and found nothing. */ + (void)load_descriptor_values(iter); return false; + } } -extern void _ebss; +bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, + const pb_field_t *field) { + if (field->data_size == sizeof(pb_callback_t)) { + pb_callback_t *pCallback = (pb_callback_t *)field->pData; -//Return true if there is less than MIN_BSS_STACK_GAP bytes available in the stack -bool check_stack_overflow(uint16_t min_bss_stack_gap){ - uint32_t stack_top = 0; + if (pCallback != NULL) { + if (istream != NULL && pCallback->funcs.decode != NULL) { + return pCallback->funcs.decode(istream, field, &pCallback->arg); + } - //PRINTF("+++++++Stack remaining: CUR STACK ADDR: %p, EBSS: %p, diff: %d\n", &stack_top, &_ebss, ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); - if(((uintptr_t)&stack_top) < (((uintptr_t)&_ebss) + min_bss_stack_gap)){ - return true; + if (ostream != NULL && pCallback->funcs.encode != NULL) { + return pCallback->funcs.encode(ostream, field, &pCallback->arg); + } } - - return false; + } + + return true; /* Success, but didn't do anything */ } + +#ifdef PB_VALIDATE_UTF8 + +/* This function checks whether a string is valid UTF-8 text. + * + * Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c + * Original copyright: Markus Kuhn 2005-03-30 + * Licensed under "Short code license", which allows use under MIT license or + * any compatible with it. + */ + +bool pb_validate_utf8(const char *str) { + const pb_byte_t *s = (const pb_byte_t *)str; + while (*s) { + if (*s < 0x80) { + /* 0xxxxxxx */ + s++; + } else if ((s[0] & 0xe0) == 0xc0) { + /* 110XXXXx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[0] & 0xfe) == 0xc0) /* overlong? */ + return false; + else + s += 2; + } else if ((s[0] & 0xf0) == 0xe0) { + /* 1110XXXX 10Xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || + (s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */ + (s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */ + (s[0] == 0xef && s[1] == 0xbf && + (s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ + return false; + else + s += 3; + } else if ((s[0] & 0xf8) == 0xf0) { + /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ + if ((s[1] & 0xc0) != 0x80 || (s[2] & 0xc0) != 0x80 || + (s[3] & 0xc0) != 0x80 || + (s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */ + (s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */ + return false; + else + s += 4; + } else { + return false; + } + } + + return true; +} + +#endif diff --git a/src/nanopb/pb_common.h b/src/nanopb/pb_common.h index 60b3d374..8d475999 100644 --- a/src/nanopb/pb_common.h +++ b/src/nanopb/pb_common.h @@ -11,20 +11,14 @@ extern "C" { #endif -/* Iterator for pb_field_t list */ -struct pb_field_iter_s { - const pb_field_t *start; /* Start of the pb_field_t array */ - const pb_field_t *pos; /* Current position of the iterator */ - unsigned required_field_index; /* Zero-based index that counts only the required fields */ - void *dest_struct; /* Pointer to start of the structure */ - void *pData; /* Pointer to current field value */ - void *pSize; /* Pointer to count/has field */ -}; -typedef struct pb_field_iter_s pb_field_iter_t; - /* Initialize the field iterator structure to beginning. * Returns false if the message type is empty. */ -bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct); +bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, + void *message); + +/* Get a field iterator for extension field. */ +bool pb_field_iter_begin_extension(pb_field_iter_t *iter, + pb_extension_t *extension); /* Advance the iterator to the next field. * Returns false when the iterator wraps back to the first field. */ @@ -34,9 +28,13 @@ bool pb_field_iter_next(pb_field_iter_t *iter); * Returns false if no such field exists. */ bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag); +#ifdef PB_VALIDATE_UTF8 +/* Validate UTF-8 text string */ +bool pb_validate_utf8(const char *s); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif #endif - diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index 1b95bf2c..c436f6e9 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -1,15 +1,12 @@ +#include "../ui/transactions/protobuf.h" #include "pb_custom.h" #include "os.h" #include "pb_decode.h" +#include "../main.h" /******************************************************* * Ledger's APDU pb_istream_from_apdu_t implementation * *******************************************************/ -#define OFFSET_P1 2 -#define OFFSET_LC 4 -#define OFFSET_DATA 5 -#define P1_FIRST 0x00 -#define P1_NEXT 0x80 #define MAX_FETCH_ATTEMPTS 10 @@ -19,105 +16,114 @@ #define ERR_WRONG_MESSAGE_SIZE 0x6006 #define ERR_WRONG_PARAMETER 0x6007 -//#define PRINTF_PB(...) //PRINTF(__VA_ARGS__) +#define PRINTF_PB(...) // PRINTF(__VA_ARGS__) -#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) - #define checkreturn +#if !defined(__GNUC__) || (__GNUC__ < 3) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +#define checkreturn #else - #define checkreturn __attribute__((warn_unused_result)) +#define checkreturn __attribute__((warn_unused_result)) #endif -typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; - - -void inline fetch_new_apdu(pb_istream_from_apdu_ctx_t *state) __attribute__((no_instrument_function)); - -void fetch_new_apdu(pb_istream_from_apdu_ctx_t *state){ - - unsigned int rx; - G_io_apdu_buffer[0] = 0x90; - G_io_apdu_buffer[1] = 0x00; - rx = io_exchange(CHANNEL_APDU, 2); - - if(G_io_apdu_buffer[OFFSET_P1] != P1_NEXT){ - THROW(ERR_WRONG_PARAMETER); - } - else if(state->bytes_stored + G_io_apdu_buffer[OFFSET_LC] > sizeof(state->data)){ - PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, G_io_apdu_buffer[OFFSET_LC]); - THROW(ERR_BUFFER_TOO_SMALL); - } - - state->total_received += G_io_apdu_buffer[OFFSET_LC]; - - if (state->total_received > state->total_size) - { - PRINTF("total_rec: %d total_size %d\n", state->total_received , state->total_size); - THROW(ERR_WRONG_MESSAGE_SIZE); - } - +typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, + void *dest) checkreturn; + +void inline fetch_new_apdu(uiProtobuf_t *state) + __attribute__((no_instrument_function)); + +void fetch_new_apdu(uiProtobuf_t *state) { + + unsigned int rx; + G_io_apdu_buffer[0] = 0x90; + G_io_apdu_buffer[1] = 0x00; + rx = io_exchange(CHANNEL_APDU, 2); + if (G_io_apdu_buffer[4] != rx - 5) { + // the length of the APDU should match what's in the 5-byte header. + // If not fail. Don't want to buffer overrun or anything. + THROW(SW_CONDITIONS_NOT_SATISFIED); + } + + if (G_io_apdu_buffer[2] != P1_MORE && G_io_apdu_buffer[2] != P1_LAST) { + THROW(SW_INCORRECT_P1_P2); + } else if (state->bytes_stored + G_io_apdu_buffer[4] > sizeof(state->data)) { + PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, + G_io_apdu_buffer[4]); + THROW(ERR_BUFFER_TOO_SMALL); + } + + if (tmp_ctx.signing_context.step == 7) { + THROW(SW_INCORRECT_P1_P2); + } + + state->total_received += G_io_apdu_buffer[4]; } -bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) -{ - pb_istream_from_apdu_ctx_t *state; - uint16_t bytes_not_read_yet; - uint8_t fetch_attempts; - const pb_byte_t *source; - - if(count > MAX_PB_ELEMENT_SIZE){ - THROW(ERR_PB_READ_IS_TOO_BIG); +bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { + uiProtobuf_t *state; + uint16_t bytes_not_read_yet; + uint8_t fetch_attempts; + const pb_byte_t *source; + + if (count > MAX_PB_ELEMENT_SIZE) { + THROW(ERR_PB_READ_IS_TOO_BIG); + } + + state = (uiProtobuf_t *)stream->state; + + bytes_not_read_yet = state->bytes_stored - state->read_offset; + + PRINTF_PB("r: %d re: %d s %d\n", count, bytes_not_read_yet, + state->bytes_stored); + + /* not enough data has been received and deciphered, we fetch a new apdu or + stop the s tream if the last apdu was already received*/ + if (count > bytes_not_read_yet) { + // shift data to the beginning of the buffer + os_memmove(state->data, state->data + state->read_offset, + state->bytes_stored - state->read_offset); + state->bytes_stored = bytes_not_read_yet; + state->read_offset = 0; + + PRINTF_PB("SHIFT LEFT: available: %d\n", bytes_not_read_yet); + + // loop over apdu fetching while there's not enough bytes stored to feed the + // amount requested + fetch_attempts = 0; + while (count > bytes_not_read_yet) { + + if (++fetch_attempts > MAX_FETCH_ATTEMPTS) { + THROW(ERR_NOT_ENOUGH_BYTES_RECEIVED); + } else if (state->total_received == state->total_size) { + // Everything has been received, signal to nanopb that it's time to end + // decoding + stream->bytes_left = 0; + return false; + } + + fetch_new_apdu(state); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, + G_io_apdu_buffer + 5, G_io_apdu_buffer[4], NULL, 0); + os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, + G_io_apdu_buffer[4]); + + state->bytes_stored += G_io_apdu_buffer[4]; + bytes_not_read_yet = state->bytes_stored - state->read_offset; } - - state = (pb_istream_from_apdu_ctx_t*)stream->state; - - bytes_not_read_yet = state->bytes_stored-state->read_offset; - - PRINTF("read: %d readable: %d stored %d\n", count, bytes_not_read_yet, state->bytes_stored); - - /* not enough data has been received and deciphered, we fetch a new apdu or stop the s - tream if the last apdu was already received*/ - if(count > bytes_not_read_yet){ - // shift data to the beginning of the buffer - os_memmove(state->data, state->data+state->read_offset, state->bytes_stored - state->read_offset); - state->bytes_stored = bytes_not_read_yet; - state->read_offset = 0; - - PRINTF("SHIFT LEFT: available: %d\n", bytes_not_read_yet); - - // loop over apdu fetching while there's not enough bytes stored to feed the amount requested - fetch_attempts = 0; - while(count > bytes_not_read_yet){ - - if (++fetch_attempts > MAX_FETCH_ATTEMPTS) - { - THROW(ERR_NOT_ENOUGH_BYTES_RECEIVED); - } - else if(state->total_received == state->total_size){ - // Everything has been received, signal to nanopb that it's time to end decoding - stream->bytes_left = 0; - return false; - } - - fetch_new_apdu(state); - - os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + OFFSET_DATA, G_io_apdu_buffer[OFFSET_LC]); - - state->bytes_stored += G_io_apdu_buffer[OFFSET_LC]; - bytes_not_read_yet = state->bytes_stored - state->read_offset; - } - } - - // extract data to output buffer - source = (const pb_byte_t*)state->data + state->read_offset; - state->read_offset += count; - - if (buf != NULL) - { - for (uint16_t i = 0; i < count; i++) - buf[i] = source[i]; - } - - return true; + } + if (state->total_size <= state->total_read) { + stream->bytes_left = 0; + return false; + } + // extract data to output buffer + source = (const pb_byte_t *)state->data + state->read_offset; + state->read_offset += count; + state->total_read += count; + if (buf != NULL) { + for (uint16_t i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; } /* @@ -127,29 +133,30 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) init_buffer_size: length of init_buffer total_buffer_size: total length of the message to receive */ -pb_istream_t pb_istream_from_apdu(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size) -{ - pb_istream_t stream; - - stream.callback = &apdu_read;; - - stream.state = ctx; - stream.bytes_left = SIZE_MAX; +pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, + uint16_t total_buffer_size) { + pb_istream_t stream; + stream.callback = &apdu_read; + stream.state = ctx; + stream.bytes_left = SIZE_MAX; #ifndef PB_NO_ERRMSG - stream.errmsg = NULL; + stream.errmsg = NULL; #endif - os_memset(ctx, 0, sizeof(pb_istream_from_apdu_ctx_t)); - PRINTF("Init buffer:\n%.*H\n", init_buffer_size, init_buffer); - ctx->total_received = init_buffer_size; - ctx->total_size = total_buffer_size; - os_memmove(ctx->data, init_buffer, init_buffer_size); - ctx->bytes_stored = init_buffer_size; - ctx->read_offset = 0; + os_memset(ctx, 0, sizeof(uiProtobuf_t)); + ctx->total_received = init_buffer_size; + ctx->total_size = total_buffer_size; + os_memmove(ctx->data, init_buffer, init_buffer_size); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, init_buffer, + init_buffer_size, NULL, 0); + ctx->bytes_stored = init_buffer_size; + ctx->read_offset = 0; + ctx->total_read = 0; #ifdef HAVE_PRINTF - // Set call stack monitoring level to 0 - G_depth = 0; + // Set call stack monitoring level to 0 + // G_depth = 0; #endif - return stream; -} \ No newline at end of file + return stream; +} diff --git a/src/nanopb/pb_custom.h b/src/nanopb/pb_custom.h index 9a454560..eafe5a8e 100644 --- a/src/nanopb/pb_custom.h +++ b/src/nanopb/pb_custom.h @@ -5,27 +5,21 @@ #include "os.h" #include "cx.h" #include "pb.h" +#include "main.h" - -/* Custom `pb_istream_s.state` structure that handles decoding from apdu streaming */ +/* Custom `pb_istream_s.state` structure that handles decoding from apdu + * streaming */ #define PB_DECODING_FAILED 0 -// Maximum size of a single serialized pb element #define MAX_PB_ELEMENT_SIZE 100 -// Maximum size of an APDU payload. Can be reduced to save some bytes, but then the host has to ensure that it doesn't send APDU payloads bigger than this value. -#define MAX_APDU_PAYLOAD_SIZE 255 - - -typedef struct{ - uint8_t data[MAX_PB_ELEMENT_SIZE + MAX_APDU_PAYLOAD_SIZE]; // size of the biggest nanopb element serialized + size of an APDU (worst case scenario) - uint32_t read_offset; // nanopb read offset, everything before it has been succesfully decoded - uint32_t bytes_stored; // number of bytes currently stored in "data" - uint32_t total_size; // total size of the nanopb structure being received - uint32_t total_received; // number of bytes received since decoding began - -} pb_istream_from_apdu_ctx_t; - -pb_istream_t apdu_pb_istream(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size); -pb_istream_t pb_istream_from_apdu(pb_istream_from_apdu_ctx_t* ctx, uint8_t* init_buffer, uint8_t init_buffer_size, uint32_t total_buffer_size); +pb_istream_t apdu_pb_istream(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, + uint16_t total_buffer_size); +pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, + uint16_t total_buffer_size); +bool transaction_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg); +bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg); #endif \ No newline at end of file diff --git a/src/nanopb/pb_decode.c b/src/nanopb/pb_decode.c index 17cc3e9c..a7acc6d6 100644 --- a/src/nanopb/pb_decode.c +++ b/src/nanopb/pb_decode.c @@ -7,53 +7,76 @@ * are propagated correctly. On other compilers and gcc before 3.4.0 just * ignore the annotation. */ -#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) - #define checkreturn +#if !defined(__GNUC__) || (__GNUC__ < 3) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +#define checkreturn #else - #define checkreturn __attribute__((warn_unused_result)) +#define checkreturn __attribute__((warn_unused_result)) #endif +#include "os.h" #include "pb.h" #include "pb_decode.h" #include "pb_common.h" -#include "os.h" - /************************************** * Declarations internal to this file * **************************************/ -typedef bool (*pb_decoder_t)(pb_istream_t *stream, const pb_field_t *field, void *dest) checkreturn; - -static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); -static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size); -static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter); -static bool inline checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) __attribute__((no_instrument_function)); -static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension); -static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type); -static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter); +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, + size_t count); +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, + uint32_t *dest, bool *eof); +static bool checkreturn read_raw_value(pb_istream_t *stream, + pb_wire_type_t wire_type, pb_byte_t *buf, + size_t *size); +static bool checkreturn decode_basic_field(pb_istream_t *stream, + pb_field_iter_t *field); +static bool checkreturn decode_static_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field); +static bool checkreturn decode_pointer_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field); +static bool checkreturn decode_callback_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field); +static bool checkreturn decode_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field); +static bool checkreturn default_extension_decoder(pb_istream_t *stream, + pb_extension_t *extension, + uint32_t tag, + pb_wire_type_t wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, + pb_wire_type_t wire_type, + pb_field_iter_t *iter); static bool checkreturn find_extension_field(pb_field_iter_t *iter); -static void pb_field_set_to_default(pb_field_iter_t *iter); -static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct); -static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool inline checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) __attribute__((no_instrument_function)); -static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest); -static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest); +static bool pb_message_set_to_defaults(pb_field_iter_t *iter); +static bool checkreturn pb_dec_bool(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_varint(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_fixed(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_string(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, + const pb_field_iter_t *field); static bool checkreturn pb_skip_varint(pb_istream_t *stream); static bool checkreturn pb_skip_string(pb_istream_t *stream); #ifdef PB_ENABLE_MALLOC -static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size); -static bool checkreturn pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter); -static void pb_release_single_field(const pb_field_iter_t *iter); -static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter); +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, + size_t data_size, size_t array_size); +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field); +static bool checkreturn pb_release_union_field(pb_istream_t *stream, + pb_field_iter_t *field); +static void pb_release_single_field(pb_field_iter_t *field); #endif #ifdef PB_WITHOUT_64BIT @@ -64,512 +87,413 @@ static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter); #define pb_uint64_t uint64_t #endif -/* --- Function pointers to field decoders --- - * Order in the array must match pb_action_t LTYPE numbering. - */ -static const pb_decoder_t PB_DECODERS[PB_LTYPES_COUNT] = { - &pb_dec_varint, - &pb_dec_uvarint, - &pb_dec_svarint, - &pb_dec_fixed32, - &pb_dec_fixed64, - - &pb_dec_bytes, - &pb_dec_string, - &pb_dec_submessage, - NULL, /* extensions */ - &pb_dec_fixed_length_bytes -}; - -extern void _ebss; -extern void _estack; -int G_depth; -int last_stack_left; -typedef struct addr_to_fname_s { - const void* const addr; - const char* const name; -} addr_to_fname_t; - -static bool checkreturn inline decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) __attribute__((no_instrument_function)); -static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf); - -const addr_to_fname_t addr_to_fnames[] = { - { pb_readbyte, "pb_readbyte" }, - { decode_pointer_field, "decode_pointer_field" }, -#ifdef PB_ENABLE_MALLOC - { initialize_pointer_field, "initialize_pointer_field" }, - { allocate_field, "allocate_field" }, - { pb_release_union_field, "pb_release_union_field" }, - { pb_release_single_field, "pb_release_single_field" }, - { pb_release, "pb_release" }, -#endif - { pb_decode, "pb_decode" }, - { pb_message_set_to_defaults, "pb_message_set_to_defaults" }, - { pb_decode_noinit, "pb_decode_noinit" }, - { buf_read, "buf_read" }, - { read_raw_value, "read_raw_value" }, - { decode_static_field, "decode_static_field" }, - { decode_callback_field, "decode_callback_field" }, - { decode_field, "decode_field" }, - { iter_from_extension, "iter_from_extension" }, - { default_extension_decoder, "default_extension_decoder" }, - { decode_extension, "decode_extension" }, - { find_extension_field, "find_extension_field" }, - { pb_field_set_to_default, "pb_field_set_to_default" }, - { pb_message_set_to_defaults, "pb_message_set_to_defaults" }, - { pb_dec_varint, "pb_dec_varint" }, - { pb_decode_varint32_eof, "pb_decode_varint32_eof" }, - { pb_dec_uvarint, "pb_dec_uvarint" }, - { pb_dec_svarint, "pb_dec_svarint" }, - { pb_dec_fixed32, "pb_dec_fixed32" }, - { pb_dec_fixed64, "pb_dec_fixed64" }, - { pb_dec_bytes, "pb_dec_bytes" }, - { pb_dec_string, "pb_dec_string" }, - { pb_dec_submessage, "pb_dec_submessage" }, - { pb_dec_fixed_length_bytes, "pb_dec_fixed_length_bytes" }, - { pb_skip_varint, "pb_skip_varint" }, - { pb_skip_string, "pb_skip_string" }, - { pb_decode_delimited, "pb_decode_delimited" }, - { pb_decode_delimited_noinit, "pb_decode_delimited_noinit" }, - { pb_decode_nullterminated, "pb_decode_nullterminated" }, - { pb_istream_from_buffer, "pb_istream_from_buffer" }, - { pb_read, "pb_read" }, - { pb_decode_tag, "pb_decode_tag" }, - { pb_skip_field, "pb_skip_field" }, - // { pb_decode_varint, "pb_decode_varint" }, - { pb_decode_varint32, "pb_decode_varint32" }, - { pb_decode_svarint, "pb_decode_svarint" }, - { pb_decode_fixed32, "pb_decode_fixed32" }, - { pb_make_string_substream, "pb_make_string_substream" }, - { pb_close_string_substream, "pb_close_string_substream" }, - { decode_pointer_field, "decode_pointer_field" }, - { decode_callback_field, "decode_callback_field" } -}; - -const char* addr_to_fname(void* func) __attribute__((no_instrument_function)); -const char* addr_to_fname(void* func){ - for(int i = 0; i < sizeof(addr_to_fnames)/sizeof(*addr_to_fnames); i++){ - if(PIC(addr_to_fnames[i].addr) == func){ - return (const char*)(PIC(addr_to_fnames[i].name)); - } - } - return ""; -} - -void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function)); -void __cyg_profile_func_enter( void *func, void *callsite ) -{ - const char* fname = addr_to_fname(func); - for(int i = 0; i < G_depth; i++){ - PRINTF(" "); - } - PRINTF("-> %p '%s' [from %p], STACK %p, left: %d\n", func, fname, callsite, &fname, ((void*)&fname) - &_ebss); //, last_stack_left - (((void*)&fname) - &_ebss)); - last_stack_left = ((void*)&fname) - &_ebss; - G_depth++; -} -void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function)); -void __cyg_profile_func_exit( void *func, void *callsite ) -{ - const char* fname = addr_to_fname(func); - // last_stack_left = ((void*)&fname) - &_ebss; - G_depth--; - for(int i = 0; i < G_depth; i++){ - PRINTF(" "); - } - PRINTF("<- %p '%s' [from %p], left: %d\n", func, fname, callsite, ((void*)&fname) - &_ebss); - // last_stack_left = ((void*)&fname) - &_ebss; -} +typedef struct { + uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32]; +} pb_fields_seen_t; /******************************* * pb_istream_t implementation * *******************************/ -static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) -{ - size_t i; - const pb_byte_t *source = (const pb_byte_t*)stream->state; - stream->state = (pb_byte_t*)stream->state + count; - - if (buf != NULL) - { - for (i = 0; i < count; i++) - buf[i] = source[i]; - } - - return true; +static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, + size_t count) { + size_t i; + const pb_byte_t *source = (const pb_byte_t *)stream->state; + stream->state = (pb_byte_t *)stream->state + count; + + if (buf != NULL) { + for (i = 0; i < count; i++) + buf[i] = source[i]; + } + + return true; } -bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) -{ +bool checkreturn pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { + if (count == 0) + return true; + #ifndef PB_BUFFER_ONLY - if (buf == NULL && stream->callback != buf_read) - { - /* Skip input bytes */ - pb_byte_t tmp[16]; - while (count > 16) - { - if (!pb_read(stream, tmp, 16)) - return false; - - count -= 16; - } - - return pb_read(stream, tmp, count); - } + if (buf == NULL && stream->callback != buf_read) { + /* Skip input bytes */ + pb_byte_t tmp[16]; + while (count > 16) { + if (!pb_read(stream, tmp, 16)) + return false; + + count -= 16; + } + + return pb_read(stream, tmp, count); + } #endif - if (stream->bytes_left < count) - PB_RETURN_ERROR(stream, "end-of-stream"); - + if (stream->bytes_left < count) + PB_RETURN_ERROR(stream, "end-of-stream"); + #ifndef PB_BUFFER_ONLY - if (!stream->callback(stream, buf, count)) - PB_RETURN_ERROR(stream, "io error"); + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); #else - if (!buf_read(stream, buf, count)) - return false; + if (!buf_read(stream, buf, count)) + return false; #endif - - stream->bytes_left -= count; - return true; + + stream->bytes_left -= count; + return true; } /* Read a single byte from input stream. buf may not be NULL. * This is an optimization for the varint decoding. */ -static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) -{ - if (stream->bytes_left == 0) - PB_RETURN_ERROR(stream, "end-of-stream"); +static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf) { + if (stream->bytes_left == 0) + PB_RETURN_ERROR(stream, "end-of-stream"); #ifndef PB_BUFFER_ONLY - if (!stream->callback(stream, buf, 1)) - PB_RETURN_ERROR(stream, "io error"); + if (!stream->callback(stream, buf, 1)) + PB_RETURN_ERROR(stream, "io error"); #else - *buf = *(const pb_byte_t*)stream->state; - stream->state = (pb_byte_t*)stream->state + 1; + *buf = *(const pb_byte_t *)stream->state; + stream->state = (pb_byte_t *)stream->state + 1; #endif + stream->bytes_left--; - stream->bytes_left--; - - return true; + return true; } -pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) -{ - pb_istream_t stream; - /* Cast away the const from buf without a compiler error. We are - * careful to use it only in a const manner in the callbacks. - */ - union { - void *state; - const void *c_state; - } state; +pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize) { + pb_istream_t stream; + /* Cast away the const from buf without a compiler error. We are + * careful to use it only in a const manner in the callbacks. + */ + union { + void *state; + const void *c_state; + } state; #ifdef PB_BUFFER_ONLY - stream.callback = NULL; + stream.callback = NULL; #else - stream.callback = &buf_read; + stream.callback = &buf_read; #endif - state.c_state = buf; - stream.state = state.state; - stream.bytes_left = bufsize; + state.c_state = buf; + stream.state = state.state; + stream.bytes_left = bufsize; #ifndef PB_NO_ERRMSG - stream.errmsg = NULL; + stream.errmsg = NULL; #endif - return stream; + return stream; } /******************** * Helper functions * ********************/ -static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof) -{ - pb_byte_t byte; - uint32_t result; - - if (!pb_readbyte(stream, &byte)) - { - if (stream->bytes_left == 0) - { - if (eof) - { - *eof = true; - } - } +static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, + uint32_t *dest, bool *eof) { + pb_byte_t byte; + uint32_t result; - return false; - } - - if ((byte & 0x80) == 0) - { - /* Quick case, 1 byte value */ - result = byte; + if (!pb_readbyte(stream, &byte)) { + if (stream->bytes_left == 0) { + if (eof) { + *eof = true; + } } - else - { - /* Multibyte case */ - uint_fast8_t bitpos = 7; - result = byte & 0x7F; - - do - { - if (!pb_readbyte(stream, &byte)) - return false; - - if (bitpos >= 32) - { - /* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */ - uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; - - if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension)) - { - PB_RETURN_ERROR(stream, "varint overflow"); - } - } - else - { - result |= (uint32_t)(byte & 0x7F) << bitpos; - } - bitpos = (uint_fast8_t)(bitpos + 7); - } while (byte & 0x80); - - if (bitpos == 35 && (byte & 0x70) != 0) - { - /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ - PB_RETURN_ERROR(stream, "varint overflow"); + + return false; + } + + if ((byte & 0x80) == 0) { + /* Quick case, 1 byte value */ + result = byte; + } else { + /* Multibyte case */ + uint_fast8_t bitpos = 7; + result = byte & 0x7F; + + do { + if (!pb_readbyte(stream, &byte)) + return false; + + if (bitpos >= 32) { + /* Note: The varint could have trailing 0x80 bytes, or 0xFF for + * negative. */ + uint8_t sign_extension = (bitpos < 63) ? 0xFF : 0x01; + + if ((byte & 0x7F) != 0x00 && + ((result >> 31) == 0 || byte != sign_extension)) { + PB_RETURN_ERROR(stream, "varint overflow"); } - } - - *dest = result; - return true; + } else { + result |= (uint32_t)(byte & 0x7F) << bitpos; + } + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + if (bitpos == 35 && (byte & 0x70) != 0) { + /* The last byte was at bitpos=28, so only bottom 4 bits fit. */ + PB_RETURN_ERROR(stream, "varint overflow"); + } + } + + *dest = result; + return true; } -bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) -{ - return pb_decode_varint32_eof(stream, dest, NULL); +bool checkreturn pb_decode_varint32(pb_istream_t *stream, uint32_t *dest) { + return pb_decode_varint32_eof(stream, dest, NULL); } #ifndef PB_WITHOUT_64BIT -bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) -{ - pb_byte_t byte; - uint_fast8_t bitpos = 0; - uint64_t result = 0; - - do - { - if (bitpos >= 64) - PB_RETURN_ERROR(stream, "varint overflow"); - - if (!pb_readbyte(stream, &byte)) - return false; - result |= (uint64_t)(byte & 0x7F) << bitpos; - bitpos = (uint_fast8_t)(bitpos + 7); - } while (byte & 0x80); - - *dest = result; - return true; +bool checkreturn pb_decode_varint(pb_istream_t *stream, uint64_t *dest) { + pb_byte_t byte; + uint_fast8_t bitpos = 0; + uint64_t result = 0; + + do { + if (bitpos >= 64) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_readbyte(stream, &byte)) + return false; + + result |= (uint64_t)(byte & 0x7F) << bitpos; + bitpos = (uint_fast8_t)(bitpos + 7); + } while (byte & 0x80); + + *dest = result; + return true; } #endif -bool checkreturn pb_skip_varint(pb_istream_t *stream) -{ - pb_byte_t byte; - do - { - if (!pb_read(stream, &byte, 1)) - return false; - } while (byte & 0x80); - return true; +bool checkreturn pb_skip_varint(pb_istream_t *stream) { + pb_byte_t byte; + do { + if (!pb_read(stream, &byte, 1)) + return false; + } while (byte & 0x80); + return true; } -bool checkreturn pb_skip_string(pb_istream_t *stream) -{ - uint32_t length; - if (!pb_decode_varint32(stream, &length)) - return false; - - return pb_read(stream, NULL, length); +bool checkreturn pb_skip_string(pb_istream_t *stream) { + uint32_t length; + if (!pb_decode_varint32(stream, &length)) + return false; + + if ((size_t)length != length) { + PB_RETURN_ERROR(stream, "size too large"); + } + + return pb_read(stream, NULL, (size_t)length); } -bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof) -{ - uint32_t temp; - *eof = false; - *wire_type = (pb_wire_type_t) 0; - *tag = 0; - - if (!pb_decode_varint32_eof(stream, &temp, eof)) - { - return false; - } - - if (temp == 0) - { - *eof = true; /* Special feature: allow 0-terminated messages. */ - return false; - } - - *tag = temp >> 3; - *wire_type = (pb_wire_type_t)(temp & 7); - - return true; +bool checkreturn pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, + uint32_t *tag, bool *eof) { + uint32_t temp; + *eof = false; + *wire_type = (pb_wire_type_t)0; + *tag = 0; + + if (!pb_decode_varint32_eof(stream, &temp, eof)) { + return false; + } + + *tag = temp >> 3; + *wire_type = (pb_wire_type_t)(temp & 7); + return true; } -bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) -{ - switch (wire_type) - { - case PB_WT_VARINT: return pb_skip_varint(stream); - case PB_WT_64BIT: return pb_read(stream, NULL, 8); - case PB_WT_STRING: return pb_skip_string(stream); - case PB_WT_32BIT: return pb_read(stream, NULL, 4); - default: PB_RETURN_ERROR(stream, "invalid wire_type"); - } +bool checkreturn pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type) { + switch (wire_type) { + case PB_WT_VARINT: + return pb_skip_varint(stream); + case PB_WT_64BIT: + return pb_read(stream, NULL, 8); + case PB_WT_STRING: + return pb_skip_string(stream); + case PB_WT_32BIT: + return pb_read(stream, NULL, 4); + default: + PB_RETURN_ERROR(stream, "invalid wire_type"); + } } /* Read a raw value to buffer, for the purpose of passing it to callback as * a substream. Size is maximum size on call, and actual size on return. */ -static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size) -{ - size_t max_size = *size; - switch (wire_type) - { - case PB_WT_VARINT: - *size = 0; - do - { - (*size)++; - if (*size > max_size) return false; - if (!pb_read(stream, buf, 1)) return false; - } while (*buf++ & 0x80); - return true; - - case PB_WT_64BIT: - *size = 8; - return pb_read(stream, buf, 8); - - case PB_WT_32BIT: - *size = 4; - return pb_read(stream, buf, 4); - - default: PB_RETURN_ERROR(stream, "invalid wire_type"); - } +static bool checkreturn read_raw_value(pb_istream_t *stream, + pb_wire_type_t wire_type, pb_byte_t *buf, + size_t *size) { + size_t max_size = *size; + switch (wire_type) { + case PB_WT_VARINT: + *size = 0; + do { + (*size)++; + if (*size > max_size) + PB_RETURN_ERROR(stream, "varint overflow"); + + if (!pb_read(stream, buf, 1)) + return false; + } while (*buf++ & 0x80); + return true; + + case PB_WT_64BIT: + *size = 8; + return pb_read(stream, buf, 8); + + case PB_WT_32BIT: + *size = 4; + return pb_read(stream, buf, 4); + + case PB_WT_STRING: + /* Calling read_raw_value with a PB_WT_STRING is an error. + * Explicitly handle this case and fallthrough to default to avoid + * compiler warnings. + */ + + default: + PB_RETURN_ERROR(stream, "invalid wire_type"); + } } /* Decode string length from stream and return a substream with limited length. * Remember to close the substream using pb_close_string_substream(). */ -bool checkreturn pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream) -{ - uint32_t size; - if (!pb_decode_varint32(stream, &size)) - return false; - - *substream = *stream; - if (substream->bytes_left < size) - PB_RETURN_ERROR(stream, "parent stream too short"); - - substream->bytes_left = size; - stream->bytes_left -= size; - return true; +bool checkreturn pb_make_string_substream(pb_istream_t *stream, + pb_istream_t *substream) { + uint32_t size; + if (!pb_decode_varint32(stream, &size)) + return false; + + *substream = *stream; + if (substream->bytes_left < size) + PB_RETURN_ERROR(stream, "parent stream too short"); + + substream->bytes_left = (size_t)size; + stream->bytes_left -= (size_t)size; + return true; } -bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream) -{ - if (substream->bytes_left) { - if (!pb_read(substream, NULL, substream->bytes_left)) - return false; - } +bool checkreturn pb_close_string_substream(pb_istream_t *stream, + pb_istream_t *substream) { + if (substream->bytes_left) { + if (!pb_read(substream, NULL, substream->bytes_left)) + return false; + } - stream->state = substream->state; + stream->state = substream->state; #ifndef PB_NO_ERRMSG - stream->errmsg = substream->errmsg; + stream->errmsg = substream->errmsg; #endif - return true; + return true; } /************************* * Decode a single field * *************************/ -pb_type_t type; -pb_decoder_t func; -static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) -{ - type = ((const pb_field_t *)PIC(iter->pos))->type; - func = (pb_decoder_t)PIC(PB_DECODERS[PB_LTYPE(type)]); - - switch (PB_HTYPE(type)) - { - case PB_HTYPE_REQUIRED: - return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); - - case PB_HTYPE_OPTIONAL: - if (iter->pSize != iter->pData) - *(bool*)iter->pSize = true; - return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); - - case PB_HTYPE_REPEATED: - if (wire_type == PB_WT_STRING - && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) - { -#ifndef PROTO2_SUPPORT - return false; -#else - /* Packed array */ - bool status = true; - pb_size_t *size = (pb_size_t*)iter->pSize; - pb_istream_t substream; - if (!pb_make_string_substream(stream, &substream)) - return false; - - while (substream.bytes_left > 0 && *size < ((const pb_field_t *)PIC(iter->pos))->array_size) - { - void *pItem = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); - if (!func(&substream, ((const pb_field_t *)PIC(iter->pos)), pItem)) - { - status = false; - break; - } - (*size)++; - } - - if (substream.bytes_left != 0) - PB_RETURN_ERROR(stream, "array overflow"); - if (!pb_close_string_substream(stream, &substream)) - return false; - - return status; -#endif - } - else - { - /* Repeated field */ - pb_size_t *size = (pb_size_t*)iter->pSize; - void *pItem = (char*)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); - if (*size >= ((const pb_field_t *)PIC(iter->pos))->array_size) - PB_RETURN_ERROR(stream, "array overflow"); - - (*size)++; - return func(stream, ((const pb_field_t *)PIC(iter->pos)), pItem); - } - - case PB_HTYPE_ONEOF: - *(pb_size_t*)iter->pSize = ((const pb_field_t *)PIC(iter->pos))->tag; - if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) - { - /* We memset to zero so that any callbacks are set to NULL. - * Then set any default values. */ - memset(iter->pData, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); - pb_message_set_to_defaults((const pb_field_t*)((const pb_field_t *)PIC(iter->pos))->ptr, iter->pData); - } - return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); - - default: - PB_RETURN_ERROR(stream, "invalid field type"); +static bool checkreturn decode_basic_field(pb_istream_t *stream, + pb_field_iter_t *field) { + switch (PB_LTYPE(field->type)) { + case PB_LTYPE_BOOL: + return pb_dec_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return pb_dec_varint(stream, field); + + case PB_LTYPE_FIXED32: + case PB_LTYPE_FIXED64: + return pb_dec_fixed(stream, field); + + case PB_LTYPE_BYTES: + return pb_dec_bytes(stream, field); + + case PB_LTYPE_STRING: + return pb_dec_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + return pb_dec_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + return pb_dec_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } +} + +static bool checkreturn decode_static_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field) { + switch (PB_HTYPE(field->type)) { + case PB_HTYPE_REQUIRED: + return decode_basic_field(stream, field); + + case PB_HTYPE_OPTIONAL: + if (field->pSize != NULL) + *(bool *)field->pSize = true; + return decode_basic_field(stream, field); + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING && + PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { + /* Packed array */ + bool status = true; + pb_istream_t substream; + pb_size_t *size = (pb_size_t *)field->pSize; + field->pData = (char *)field->pField + field->data_size * (*size); + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left > 0 && *size < field->array_size) { + if (!decode_basic_field(&substream, field)) { + status = false; + break; + } + (*size)++; + field->pData = (char *)field->pData + field->data_size; + } + + if (substream.bytes_left != 0) + PB_RETURN_ERROR(stream, "array overflow"); + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } else { + /* Repeated field */ + pb_size_t *size = (pb_size_t *)field->pSize; + field->pData = (char *)field->pField + field->data_size * (*size); + + if ((*size)++ >= field->array_size) + PB_RETURN_ERROR(stream, "array overflow"); + + return decode_basic_field(stream, field); } + + case PB_HTYPE_ONEOF: + *(pb_size_t *)field->pSize = field->tag; + if (PB_LTYPE_IS_SUBMSG(field->type)) { + /* We memset to zero so that any callbacks are set to NULL. + * This is because the callbacks might otherwise have values + * from some other union field. + * If callbacks are needed inside oneof field, use .proto + * option submsg_callback to have a separate callback function + * that can set the fields before submessage is decoded. + * pb_dec_submessage() will set any default values. */ + memset(field->pData, 0, (size_t)field->data_size); + } + return decode_basic_field(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } } #ifdef PB_ENABLE_MALLOC @@ -577,999 +501,1048 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t * array_size is the number of entries to reserve in an array. * Zero size is not allowed, use pb_free() for releasing. */ -static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, size_t data_size, size_t array_size) -{ - void *ptr = *(void**)pData; - - if (data_size == 0 || array_size == 0) - PB_RETURN_ERROR(stream, "invalid size"); - - /* Check for multiplication overflows. - * This code avoids the costly division if the sizes are small enough. - * Multiplication is safe as long as only half of bits are set - * in either multiplicand. - */ - { - const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); - if (data_size >= check_limit || array_size >= check_limit) - { - const size_t size_max = (size_t)-1; - if (size_max / array_size < data_size) - { - PB_RETURN_ERROR(stream, "size too large"); - } - } +static bool checkreturn allocate_field(pb_istream_t *stream, void *pData, + size_t data_size, size_t array_size) { + void *ptr = *(void **)pData; + + if (data_size == 0 || array_size == 0) + PB_RETURN_ERROR(stream, "invalid size"); + + /* Check for multiplication overflows. + * This code avoids the costly division if the sizes are small enough. + * Multiplication is safe as long as only half of bits are set + * in either multiplicand. + */ + { + const size_t check_limit = (size_t)1 << (sizeof(size_t) * 4); + if (data_size >= check_limit || array_size >= check_limit) { + const size_t size_max = (size_t)-1; + if (size_max / array_size < data_size) { + PB_RETURN_ERROR(stream, "size too large"); + } } - - /* Allocate new or expand previous allocation */ - /* Note: on failure the old pointer will remain in the structure, - * the message must be freed by caller also on error return. */ - ptr = pb_realloc(ptr, array_size * data_size); - if (ptr == NULL) - PB_RETURN_ERROR(stream, "realloc failed"); - *(void**)pData = ptr; - return true; -} + } -/* Clear a newly allocated item in case it contains a pointer, or is a submessage. */ -static void initialize_pointer_field(void *pItem, pb_field_iter_t *iter) -{ - if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_STRING || - PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_BYTES) - { - *(void**)pItem = NULL; - } - else if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_SUBMESSAGE) - { - /* We memset to zero so that any callbacks are set to NULL. - * Then set any default values. */ - memset(pItem, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); + /* Allocate new or expand previous allocation */ + /* Note: on failure the old pointer will remain in the structure, + * the message must be freed by caller also on error return. */ + ptr = pb_realloc(ptr, array_size * data_size); + if (ptr == NULL) + PB_RETURN_ERROR(stream, "realloc failed"); + + *(void **)pData = ptr; + return true; +} - pb_message_set_to_defaults((const pb_field_t *) ((const pb_field_t *)PIC(iter->pos))->ptr, pItem); +/* Clear a newly allocated item in case it contains a pointer, or is a + * submessage. */ +static void initialize_pointer_field(void *pItem, pb_field_iter_t *field) { + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) { + *(void **)pItem = NULL; + } else if (PB_LTYPE_IS_SUBMSG(field->type)) { + /* We memset to zero so that any callbacks are set to NULL. + * Then set any default values. */ + pb_field_iter_t submsg_iter; + memset(pItem, 0, field->data_size); + + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, pItem)) { + (void)pb_message_set_to_defaults(&submsg_iter); } + } } #endif -static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) -{ +static bool checkreturn decode_pointer_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field) { #ifndef PB_ENABLE_MALLOC - PB_UNUSED(wire_type); - PB_UNUSED(iter); - PB_RETURN_ERROR(stream, "no malloc support"); + PB_UNUSED(wire_type); + PB_UNUSED(field); + PB_RETURN_ERROR(stream, "no malloc support"); #else - pb_type_t type; - pb_decoder_t func; - - type = ((const pb_field_t *)PIC(iter->pos))->type; - func = PIC(PB_DECODERS[PB_LTYPE(type)]); - - switch (PB_HTYPE(type)) - { - case PB_HTYPE_REQUIRED: - case PB_HTYPE_OPTIONAL: - case PB_HTYPE_ONEOF: - if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE && - *(void**)iter->pData != NULL) - { - // if an error has been observed, no need to release memory - if(stream->errmsg){ - return false; - } - /* Duplicate field, have to release the old allocation first. */ - pb_release_single_field(iter); - } - - if (PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - *(pb_size_t*)iter->pSize = ((const pb_field_t *)PIC(iter->pos))->tag; - } - - if (PB_LTYPE(type) == PB_LTYPE_STRING || - PB_LTYPE(type) == PB_LTYPE_BYTES) - { - return func(stream, ((const pb_field_t *)PIC(iter->pos)), iter->pData); - } - else - { - if (!allocate_field(stream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, 1)) - return false; - - initialize_pointer_field(*(void**)iter->pData, iter); - return func(stream, ((const pb_field_t *)PIC(iter->pos)), *(void**)iter->pData); - } - - case PB_HTYPE_REPEATED: - if (wire_type == PB_WT_STRING - && PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE) - { - /* Packed array, multiple items come in at once. */ - bool status = true; - pb_size_t *size = (pb_size_t*)iter->pSize; - size_t allocated_size = *size; - void *pItem; - pb_istream_t substream; - - if (!pb_make_string_substream(stream, &substream)) - return false; - - while (substream.bytes_left) - { - if ((size_t)*size + 1 > allocated_size) - { - /* Allocate more storage. This tries to guess the - * number of remaining entries. Round the division - * upwards. */ - allocated_size += (substream.bytes_left - 1) / ((const pb_field_t *)PIC(iter->pos))->data_size + 1; - if (!allocate_field(&substream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, allocated_size)) - { - status = false; - break; - } - } - - /* Decode the array entry */ - pItem = *(char**)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size); - initialize_pointer_field(pItem, iter); - if (!func(&substream, ((const pb_field_t *)PIC(iter->pos)), pItem)) - { - status = false; - break; - } - - if (*size == PB_SIZE_MAX) - { + switch (PB_HTYPE(field->type)) { + case PB_HTYPE_REQUIRED: + case PB_HTYPE_OPTIONAL: + case PB_HTYPE_ONEOF: + if (PB_LTYPE_IS_SUBMSG(field->type) && *(void **)field->pField != NULL) { + /* Duplicate field, have to release the old allocation first. */ + /* FIXME: Does this work correctly for oneofs? */ + pb_release_single_field(field); + } + + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) { + *(pb_size_t *)field->pSize = field->tag; + } + + if (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES) { + /* pb_dec_string and pb_dec_bytes handle allocation themselves */ + field->pData = field->pField; + return decode_basic_field(stream, field); + } else { + if (!allocate_field(stream, field->pField, field->data_size, 1)) + return false; + + field->pData = *(void **)field->pField; + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, field); + } + + case PB_HTYPE_REPEATED: + if (wire_type == PB_WT_STRING && + PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { + /* Packed array, multiple items come in at once. */ + bool status = true; + pb_size_t *size = (pb_size_t *)field->pSize; + size_t allocated_size = *size; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + while (substream.bytes_left) { + if ((size_t)*size + 1 > allocated_size) { + /* Allocate more storage. This tries to guess the + * number of remaining entries. Round the division + * upwards. */ + allocated_size += (substream.bytes_left - 1) / field->data_size + 1; + + if (!allocate_field(&substream, field->pField, field->data_size, + allocated_size)) { + status = false; + break; + } + } + + /* Decode the array entry */ + field->pData = *(char **)field->pField + field->data_size * (*size); + initialize_pointer_field(field->pData, field); + if (!decode_basic_field(&substream, field)) { + status = false; + break; + } + + if (*size == PB_SIZE_MAX) { #ifndef PB_NO_ERRMSG - stream->errmsg = "too many array entries"; + stream->errmsg = "too many array entries"; #endif - status = false; - break; - } - - (*size)++; - } - if (!pb_close_string_substream(stream, &substream)) - return false; - - return status; - } - else - { - /* Normal repeated field, i.e. only one item at a time. */ - pb_size_t *size = (pb_size_t*)iter->pSize; - void *pItem; - - if (*size == PB_SIZE_MAX) - PB_RETURN_ERROR(stream, "too many array entries"); - - (*size)++; - if (!allocate_field(stream, iter->pData, ((const pb_field_t *)PIC(iter->pos))->data_size, *size)) - return false; - - - pItem = *(char**)iter->pData + ((const pb_field_t *)PIC(iter->pos))->data_size * (*size - 1); - initialize_pointer_field(pItem, iter); - return func(stream, ((const pb_field_t *)PIC(iter->pos)), pItem); - } - - default: - PB_RETURN_ERROR(stream, "invalid field type"); + status = false; + break; + } + + (*size)++; + } + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; + } else { + /* Normal repeated field, i.e. only one item at a time. */ + pb_size_t *size = (pb_size_t *)field->pSize; + + if (*size == PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "too many array entries"); + + (*size)++; + if (!allocate_field(stream, field->pField, field->data_size, *size)) + return false; + + field->pData = *(char **)field->pField + field->data_size * (*size - 1); + initialize_pointer_field(field->pData, field); + return decode_basic_field(stream, field); } + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } #endif } -static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) -{ - pb_callback_t *pCallback = (pb_callback_t*)iter->pData; - -#ifdef PB_OLD_CALLBACK_STYLE - void *arg = pCallback->arg; -#else - void **arg = &(pCallback->arg); +static bool checkreturn decode_callback_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field) { + if (!field->descriptor->field_callback) + return pb_skip_field(stream, wire_type); -#endif - - if (pCallback == NULL || pCallback->funcs.decode == NULL) - return pb_skip_field(stream, wire_type); - - if (wire_type == PB_WT_STRING) - { - pb_istream_t substream; - - if (!pb_make_string_substream(stream, &substream)) - return false; - - do - { - if (!pCallback->funcs.decode(&substream, ((const pb_field_t *)PIC(iter->pos)), arg)) - PB_RETURN_ERROR(stream, "callback failed"); - } while (substream.bytes_left); - - if (!pb_close_string_substream(stream, &substream)) - return false; + if (wire_type == PB_WT_STRING) { + pb_istream_t substream; + size_t prev_bytes_left; - return true; - } - else - { - /* Copy the single scalar value to stack. - * This is required so that we can limit the stream length, - * which in turn allows to use same callback for packed and - * not-packed fields. */ - pb_istream_t substream; - pb_byte_t buffer[10]; - size_t size = sizeof(buffer); - - if (!read_raw_value(stream, wire_type, buffer, &size)) - return false; - substream = pb_istream_from_buffer(buffer, size); - - return pCallback->funcs.decode(&substream, ((const pb_field_t *)PIC(iter->pos)), arg); - } + if (!pb_make_string_substream(stream, &substream)) + return false; + + do { + prev_bytes_left = substream.bytes_left; + if (!((bool (*)(pb_istream_t * istream, pb_ostream_t * ostream, + const pb_field_iter_t *field))( + PIC(field->descriptor->field_callback)))(&substream, NULL, field)) + PB_RETURN_ERROR(stream, "callback failed"); + } while (substream.bytes_left > 0 && + substream.bytes_left < prev_bytes_left); + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return true; + } else { + /* Copy the single scalar value to stack. + * This is required so that we can limit the stream length, + * which in turn allows to use same callback for packed and + * not-packed fields. */ + pb_istream_t substream; + pb_byte_t buffer[10]; + size_t size = sizeof(buffer); + + if (!read_raw_value(stream, wire_type, buffer, &size)) + return false; + substream = pb_istream_from_buffer(buffer, size); + + return field->descriptor->field_callback(&substream, NULL, field); + } } -static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *iter) -{ +static bool checkreturn decode_field(pb_istream_t *stream, + pb_wire_type_t wire_type, + pb_field_iter_t *field) { #ifdef PB_ENABLE_MALLOC - /* When decoding an oneof field, check if there is old data that must be - * released first. */ - if (PB_HTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_HTYPE_ONEOF) - { - if (!pb_release_union_field(stream, iter)) - return false; - } + /* When decoding an oneof field, check if there is old data that must be + * released first. */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) { + if (!pb_release_union_field(stream, field)) + return false; + } #endif - - switch (PB_ATYPE(((const pb_field_t *)PIC(iter->pos))->type)) - { - case PB_ATYPE_STATIC: - return decode_static_field(stream, wire_type, iter); - - case PB_ATYPE_POINTER: - return decode_pointer_field(stream, wire_type, iter); - - case PB_ATYPE_CALLBACK: - return decode_callback_field(stream, wire_type, iter); - - default: - PB_RETURN_ERROR(stream, "invalid field type"); - } -} -static void iter_from_extension(pb_field_iter_t *iter, pb_extension_t *extension) -{ - /* Fake a field iterator for the extension field. - * It is not actually safe to advance this iterator, but decode_field - * will not even try to. */ - const pb_field_t *field = (const pb_field_t*)extension->type->arg; - (void)pb_field_iter_begin(iter, field, extension->dest); - iter->pData = extension->dest; - iter->pSize = &extension->found; - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { - /* For pointer extensions, the pointer is stored directly - * in the extension structure. This avoids having an extra - * indirection. */ - iter->pData = &extension->dest; - } + switch (PB_ATYPE(field->type)) { + case PB_ATYPE_STATIC: + return decode_static_field(stream, wire_type, field); + + case PB_ATYPE_POINTER: + return decode_pointer_field(stream, wire_type, field); + + case PB_ATYPE_CALLBACK: + return decode_callback_field(stream, wire_type, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } } -/* Default handler for extension fields. Expects a pb_field_t structure - * in extension->type->arg. */ +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ static bool checkreturn default_extension_decoder(pb_istream_t *stream, - pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type) -{ - const pb_field_t *field = (const pb_field_t*)extension->type->arg; - pb_field_iter_t iter; - - if (field->tag != tag) - return true; - - iter_from_extension(&iter, extension); - extension->found = true; - return decode_field(stream, wire_type, &iter); + pb_extension_t *extension, + uint32_t tag, + pb_wire_type_t wire_type) { + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension(&iter, extension)) + PB_RETURN_ERROR(stream, "invalid extension"); + + if (iter.tag != tag) + return true; + + extension->found = true; + return decode_field(stream, wire_type, &iter); } /* Try to decode an unknown field as an extension field. Tries each extension * decoder in turn, until one of them handles the field or loop ends. */ -static bool checkreturn decode_extension(pb_istream_t *stream, - uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter) -{ - pb_extension_t *extension = *(pb_extension_t* const *)iter->pData; - size_t pos = stream->bytes_left; - - while (extension != NULL && pos == stream->bytes_left) - { - bool status; - if (extension->type->decode) - status = extension->type->decode(stream, extension, tag, wire_type); - else - status = default_extension_decoder(stream, extension, tag, wire_type); +static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, + pb_wire_type_t wire_type, + pb_field_iter_t *iter) { + pb_extension_t *extension = *(pb_extension_t *const *)iter->pData; + size_t pos = stream->bytes_left; - if (!status) - return false; - - extension = extension->next; - } - - return true; + while (extension != NULL && pos == stream->bytes_left) { + bool status; + if (extension->type->decode) + status = extension->type->decode(stream, extension, tag, wire_type); + else + status = default_extension_decoder(stream, extension, tag, wire_type); + + if (!status) + return false; + + extension = extension->next; + } + + return true; } /* Step through the iterator until an extension field is found or until all * entries have been checked. There can be only one extension field per * message. Returns false if no extension field is found. */ -static bool checkreturn find_extension_field(pb_field_iter_t *iter) -{ - const pb_field_t *start = (const pb_field_t *)PIC(iter->pos); - - do { - if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_EXTENSION) - return true; - (void)pb_field_iter_next(iter); - } while (((const pb_field_t *)PIC(iter->pos)) != start); - - return false; +static bool checkreturn find_extension_field(pb_field_iter_t *iter) { + pb_size_t start = iter->index; + + do { + if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION) + return true; + (void)pb_field_iter_next(iter); + } while (iter->index != start); + + return false; } /* Initialize message fields to default values, recursively */ -static void pb_field_set_to_default(pb_field_iter_t *iter) -{ - pb_type_t type; - type = ((const pb_field_t *)PIC(iter->pos))->type; - if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) - { - pb_extension_t *ext = *(pb_extension_t* const *)iter->pData; - while (ext != NULL) - { - pb_field_iter_t ext_iter; - ext->found = false; - iter_from_extension(&ext_iter, ext); - pb_field_set_to_default(&ext_iter); - ext = ext->next; - } +static bool pb_field_set_to_default(pb_field_iter_t *field) { + pb_type_t type; + type = field->type; + + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { + pb_extension_t *ext = *(pb_extension_t *const *)field->pData; + while (ext != NULL) { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) { + ext->found = false; + if (!pb_message_set_to_defaults(&ext_iter)) + return false; + } + ext = ext->next; } - else if (PB_ATYPE(type) == PB_ATYPE_STATIC) - { - bool init_data = true; - if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && iter->pSize != iter->pData) - { - /* Set has_field to false. Still initialize the optional field - * itself also. */ - *(bool*)iter->pSize = false; - } - else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || - PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - /* REPEATED: Set array count to 0, no need to initialize contents. - ONEOF: Set which_field to 0. */ - *(pb_size_t*)iter->pSize = 0; - init_data = false; - } - - if (init_data) - { - if (PB_LTYPE(((const pb_field_t *)PIC(iter->pos))->type) == PB_LTYPE_SUBMESSAGE) - { - /* Initialize submessage to defaults */ - pb_message_set_to_defaults((const pb_field_t *) ((const pb_field_t *)PIC(iter->pos))->ptr, iter->pData); - } - else if (((const pb_field_t *)PIC(iter->pos))->ptr != NULL) - { - /* Initialize to default value */ - memcpy(iter->pData, ((const pb_field_t *)PIC(iter->pos))->ptr, ((const pb_field_t *)PIC(iter->pos))->data_size); - } - else - { - /* Initialize to zeros */ - memset(iter->pData, 0, ((const pb_field_t *)PIC(iter->pos))->data_size); - } - } + } else if (PB_ATYPE(type) == PB_ATYPE_STATIC) { + bool init_data = true; + if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) { + /* Set has_field to false. Still initialize the optional field + * itself also. */ + *(bool *)field->pSize = false; + } else if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) { + /* REPEATED: Set array count to 0, no need to initialize contents. + ONEOF: Set which_field to 0. */ + *(pb_size_t *)field->pSize = 0; + init_data = false; } - else if (PB_ATYPE(type) == PB_ATYPE_POINTER) - { - /* Initialize the pointer to NULL. */ - *(void**)iter->pData = NULL; - /* Initialize array count to 0. */ - if (PB_HTYPE(type) == PB_HTYPE_REPEATED || - PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - *(pb_size_t*)iter->pSize = 0; + + if (init_data) { + if (PB_LTYPE_IS_SUBMSG(field->type)) { + /* Initialize submessage to defaults */ + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, + field->pData)) { + if (!pb_message_set_to_defaults(&submsg_iter)) + return false; } + } else { + /* Initialize to zeros */ + memset(field->pData, 0, (size_t)field->data_size); + } } - else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) - { - /* Don't overwrite callback */ + } else if (PB_ATYPE(type) == PB_ATYPE_POINTER) { + /* Initialize the pointer to NULL. */ + *(void **)field->pField = NULL; + + /* Initialize array count to 0. */ + if (PB_HTYPE(type) == PB_HTYPE_REPEATED || + PB_HTYPE(type) == PB_HTYPE_ONEOF) { + *(pb_size_t *)field->pSize = 0; } + } else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK) { + /* Don't overwrite callback */ + } + + return true; } -static void pb_message_set_to_defaults(const pb_field_t fields[], void *dest_struct) -{ - pb_field_iter_t iter; - - if (!pb_field_iter_begin(&iter, fields, dest_struct)) - return; /* Empty message type */ - do - { - pb_field_set_to_default(&iter); - } while (pb_field_iter_next(&iter)); +static bool pb_message_set_to_defaults(pb_field_iter_t *iter) { + pb_istream_t defstream = PB_ISTREAM_EMPTY; + uint32_t tag = 0; + pb_wire_type_t wire_type = PB_WT_VARINT; + bool eof; + + if (iter->descriptor->default_value) { + defstream = + pb_istream_from_buffer(iter->descriptor->default_value, (size_t)-1); + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + } + + do { + if (!pb_field_set_to_default(iter)) + return false; + + if (tag != 0 && iter->tag == tag) { + /* We have a default value for this field in the defstream */ + if (!decode_field(&defstream, wire_type, iter)) + return false; + if (!pb_decode_tag(&defstream, &wire_type, &tag, &eof)) + return false; + + if (iter->pSize) + *(bool *)iter->pSize = false; + } + } while (pb_field_iter_next(iter)); + + return true; } /********************* * Decode all fields * *********************/ -#define PB_DECODE_STACK_REQUIREMENT 260 -bool checkreturn pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) -{ - if(check_stack_overflow(PB_DECODE_STACK_REQUIREMENT)) - PB_RETURN_ERROR(stream, "not enough stack"); - - // uint32_t fields_seen[(PB_MAX_REQUIRED_FIELDS + 31) / 32] = {0, 0}; - // const uint32_t allbits = ~(uint32_t)0; - // uint32_t extension_range_start = 0; - pb_field_iter_t iter; - - /* Return value ignored, as empty message types will be correctly handled by - * pb_field_iter_find() anyway. */ - (void)pb_field_iter_begin(&iter, fields, dest_struct); - while (stream->bytes_left) - { - uint32_t tag; - pb_wire_type_t wire_type; - bool eof; - if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) - { - if (eof) - break; - else - return false; - } - if (!pb_field_iter_find(&iter, tag)) - { - -#ifdef PROTO2_SUPPORT - /* No match found, check if it matches an extension. */ - if (tag >= extension_range_start) - { - if (!find_extension_field(&iter)) - extension_range_start = (uint32_t)-1; - else - extension_range_start = ((const pb_field_t*)PIC(iter.pos))->tag; - - if (tag >= extension_range_start) - { - size_t pos = stream->bytes_left; - - if (!decode_extension(stream, tag, wire_type, &iter)) - return false; - - if (pos != stream->bytes_left) - { - /* The field was handled */ - continue; - } - } - } -#endif - /* No match found, skip data */ - if (!pb_skip_field(stream, wire_type)) - return false; + +static bool checkreturn pb_decode_inner(pb_istream_t *stream, + const pb_msgdesc_t *fields, + void *dest_struct, unsigned int flags) { + uint32_t extension_range_start = 0; + + /* 'fixed_count_field' and 'fixed_count_size' track position of a repeated + * fixed count field. This can only handle _one_ repeated fixed count field + * that is unpacked and unordered among other (non repeated fixed count) + * fields. + */ + pb_size_t fixed_count_field = PB_SIZE_MAX; + pb_size_t fixed_count_size = 0; + pb_size_t fixed_count_total_size = 0; + + pb_fields_seen_t fields_seen = {{0, 0}}; + const uint32_t allbits = ~(uint32_t)0; + pb_field_iter_t iter; + + /* Return value ignored, as empty message types will be correctly handled by + * pb_field_iter_find() anyway. */ + (void)pb_field_iter_begin(&iter, fields, dest_struct); + + while (stream->bytes_left) { + uint32_t tag; + pb_wire_type_t wire_type; + bool eof; + + if (!pb_decode_tag(stream, &wire_type, &tag, &eof)) { + if (eof) + break; + else + return false; + } + + if (tag == 0) { + if (flags & PB_DECODE_NULLTERMINATED) { + break; + } else { + PB_RETURN_ERROR(stream, "zero tag"); + } + } + + if (!pb_field_iter_find(&iter, tag) || + PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) { + /* No match found, check if it matches an extension. */ + if (tag >= extension_range_start) { + if (!find_extension_field(&iter)) + extension_range_start = (uint32_t)-1; + else + extension_range_start = iter.tag; + + if (tag >= extension_range_start) { + size_t pos = stream->bytes_left; + + if (!decode_extension(stream, tag, wire_type, &iter)) + return false; + + if (pos != stream->bytes_left) { + /* The field was handled */ continue; + } } + } -#ifdef PROTO2_SUPPORT - if (PB_HTYPE(((const pb_field_t*)PIC(iter.pos))->type) == PB_HTYPE_REQUIRED - && iter.required_field_index < PB_MAX_REQUIRED_FIELDS) - { - uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); - fields_seen[iter.required_field_index >> 5] |= tmp; - } -#endif - if (!decode_field(stream, wire_type, &iter)) - return false; + /* No match found, skip data */ + if (!pb_skip_field(stream, wire_type)) + return false; + continue; } -#ifdef PROTO2_SUPPORT - /* Check that all required fields were present. */ - { - /* First figure out the number of required fields by - * seeking to the end of the field array. Usually we - * are already close to end after decoding. + /* If a repeated fixed count field was found, get size from + * 'fixed_count_field' as there is no counter contained in the struct. + */ + if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED && + iter.pSize == &iter.array_size) { + if (fixed_count_field != iter.index) { + /* If the new fixed count field does not match the previous one, + * check that the previous one is NULL or that it finished + * receiving all the expected data. */ - unsigned req_field_count; - pb_type_t last_type; - unsigned i; - do { - req_field_count = iter.required_field_index; - last_type = ((const pb_field_t*)PIC(iter.pos))->type; - } while (pb_field_iter_next(&iter)); - - /* Fixup if last field was also required. */ - if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && ((const pb_field_t*)PIC(iter.pos))->tag != 0) - req_field_count++; - - if (req_field_count > PB_MAX_REQUIRED_FIELDS) - req_field_count = PB_MAX_REQUIRED_FIELDS; - - if (req_field_count > 0) - { - /* Check the whole words */ - for (i = 0; i < (req_field_count >> 5); i++) - { - if (fields_seen[i] != allbits) - PB_RETURN_ERROR(stream, "missing required field"); - } - - /* Check the remaining bits (if any) */ - if ((req_field_count & 31) != 0) - { - if (fields_seen[req_field_count >> 5] != - (allbits >> (32 - (req_field_count & 31)))) - { - PB_RETURN_ERROR(stream, "missing required field"); - } - } + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); } + + fixed_count_field = iter.index; + fixed_count_size = 0; + fixed_count_total_size = iter.array_size; + } + + iter.pSize = &fixed_count_size; } -#endif - return true; -} + if (PB_HTYPE(iter.type) == PB_HTYPE_REQUIRED && + iter.required_field_index < PB_MAX_REQUIRED_FIELDS) { + uint32_t tmp = ((uint32_t)1 << (iter.required_field_index & 31)); + fields_seen.bitfield[iter.required_field_index >> 5] |= tmp; + } -bool checkreturn pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) -{ - bool status; - pb_message_set_to_defaults(fields, dest_struct); - status = pb_decode_noinit(stream, fields, dest_struct); -/* -#ifdef PB_ENABLE_MALLOC - if (!status) - pb_release(fields, dest_struct); -#endif -*/ - return status; + if (!decode_field(stream, wire_type, &iter)) + return false; + } + + /* Check that all elements of the last decoded fixed count field were present. + */ + if (fixed_count_field != PB_SIZE_MAX && + fixed_count_size != fixed_count_total_size) { + PB_RETURN_ERROR(stream, "wrong size for fixed count field"); + } + + /* Check that all required fields were present. */ + { + /* First figure out the number of required fields by + * seeking to the end of the field array. Usually we + * are already close to end after decoding. + */ + pb_size_t req_field_count; + pb_type_t last_type; + pb_size_t i; + do { + req_field_count = iter.required_field_index; + last_type = iter.type; + } while (pb_field_iter_next(&iter)); + + /* Fixup if last field was also required. */ + if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.tag != 0) + req_field_count++; + + if (req_field_count > PB_MAX_REQUIRED_FIELDS) + req_field_count = PB_MAX_REQUIRED_FIELDS; + + if (req_field_count > 0) { + /* Check the whole words */ + for (i = 0; i < (req_field_count >> 5); i++) { + if (fields_seen.bitfield[i] != allbits) + PB_RETURN_ERROR(stream, "missing required field"); + } + + /* Check the remaining bits (if any) */ + if ((req_field_count & 31) != 0) { + if (fields_seen.bitfield[req_field_count >> 5] != + (allbits >> (uint8_t)(32 - (req_field_count & 31)))) { + PB_RETURN_ERROR(stream, "missing required field"); + } + } + } + } + + return true; } -bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) -{ - pb_istream_t substream; - bool status; +bool checkreturn pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, + void *dest_struct, unsigned int flags) { + bool status; - if (!pb_make_string_substream(stream, &substream)) - return false; - status = pb_decode_noinit(&substream, fields, dest_struct); + if ((flags & PB_DECODE_NOINIT) == 0) { + pb_field_iter_t iter; - if (!pb_close_string_substream(stream, &substream)) - return false; - return status; -} + if (pb_field_iter_begin(&iter, fields, dest_struct)) { + if (!pb_message_set_to_defaults(&iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); + } + } -bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) -{ + if ((flags & PB_DECODE_DELIMITED) == 0) { + status = pb_decode_inner(stream, fields, dest_struct, flags); + } else { pb_istream_t substream; - bool status; - if (!pb_make_string_substream(stream, &substream)) - return false; - - status = pb_decode(&substream, fields, dest_struct); + return false; + + status = pb_decode_inner(&substream, fields, dest_struct, flags); if (!pb_close_string_substream(stream, &substream)) - return false; - return status; + return false; + } + +#ifdef PB_ENABLE_MALLOC + if (!status) + pb_release(fields, dest_struct); +#endif + + return status; } -bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct) -{ - /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */ - return pb_decode(stream, fields, dest_struct); +bool checkreturn pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, + void *dest_struct) { + return pb_decode_ex(stream, fields, dest_struct, 0); } #ifdef PB_ENABLE_MALLOC /* Given an oneof field, if there has already been a field inside this oneof, * release it before overwriting with a different one. */ -static bool pb_release_union_field(pb_istream_t *stream, pb_field_iter_t *iter) -{ - // if an error has been observed, no need to release memory - if(stream->errmsg){ - return false; - } - pb_size_t old_tag = *(pb_size_t*)iter->pSize; /* Previous which_ value */ - pb_size_t new_tag = ((const pb_field_t *)PIC(iter->pos))->tag; /* New which_ value */ +static bool pb_release_union_field(pb_istream_t *stream, + pb_field_iter_t *field) { + pb_field_iter_t old_field = *field; + pb_size_t old_tag = *(pb_size_t *)field->pSize; /* Previous which_ value */ + pb_size_t new_tag = field->tag; /* New which_ value */ - if (old_tag == 0) - return true; /* Ok, no old data in union */ + if (old_tag == 0) + return true; /* Ok, no old data in union */ - if (old_tag == new_tag) - return true; /* Ok, old data is of same type => merge */ + if (old_tag == new_tag) + return true; /* Ok, old data is of same type => merge */ - /* Release old data. The find can fail if the message struct contains - * invalid data. */ - if (!pb_field_iter_find(iter, old_tag)) - PB_RETURN_ERROR(stream, "invalid union tag"); + /* Release old data. The find can fail if the message struct contains + * invalid data. */ + if (!pb_field_iter_find(&old_field, old_tag)) + PB_RETURN_ERROR(stream, "invalid union tag"); - pb_release_single_field(iter); + pb_release_single_field(&old_field); - /* Restore iterator to where it should be. - * This shouldn't fail unless the pb_field_t structure is corrupted. */ - if (!pb_field_iter_find(iter, new_tag)) - PB_RETURN_ERROR(stream, "iterator error"); - - return true; + return true; } -static void pb_release_single_field(const pb_field_iter_t *iter) -{ - pb_type_t type; - type = ((const pb_field_t *)PIC(iter->pos))->type; +static void pb_release_single_field(pb_field_iter_t *field) { + pb_type_t type; + type = field->type; + + if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { + if (*(pb_size_t *)field->pSize != field->tag) + return; /* This is not the current field in the union */ + } + + /* Release anything contained inside an extension or submsg. + * This has to be done even if the submsg itself is statically + * allocated. */ + if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) { + /* Release fields from all extensions in the linked list */ + pb_extension_t *ext = *(pb_extension_t **)field->pData; + while (ext != NULL) { + pb_field_iter_t ext_iter; + if (pb_field_iter_begin_extension(&ext_iter, ext)) { + pb_release_single_field(&ext_iter); + } + ext = ext->next; + } + } else if (PB_LTYPE_IS_SUBMSG(type) && PB_ATYPE(type) != PB_ATYPE_CALLBACK) { + /* Release fields in submessage or submsg array */ + pb_size_t count = 1; + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) { + field->pData = *(void **)field->pField; + } else { + field->pData = field->pField; + } + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { + count = *(pb_size_t *)field->pSize; - if (PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - if (*(pb_size_t*)iter->pSize != ((const pb_field_t *)PIC(iter->pos))->tag) - return; /* This is not the current field in the union */ + if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > field->array_size) { + /* Protect against corrupted _count fields */ + count = field->array_size; + } } - /* Release anything contained inside an extension or submsg. - * This has to be done even if the submsg itself is statically - * allocated. */ - if (PB_LTYPE(type) == PB_LTYPE_EXTENSION) - { - /* Release fields from all extensions in the linked list */ - pb_extension_t *ext = *(pb_extension_t**)iter->pData; - while (ext != NULL) - { - pb_field_iter_t ext_iter; - iter_from_extension(&ext_iter, ext); - pb_release_single_field(&ext_iter); - ext = ext->next; - } + if (field->pData) { + while (count--) { + pb_release(field->submsg_desc, field->pData); + field->pData = (char *)field->pData + field->data_size; + } } - else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) - { - /* Release fields in submessage or submsg array */ - void *pItem = iter->pData; - pb_size_t count = 1; - - if (PB_ATYPE(type) == PB_ATYPE_POINTER) - { - pItem = *(void**)iter->pData; - } - - if (PB_HTYPE(type) == PB_HTYPE_REPEATED) - { - count = *(pb_size_t*)iter->pSize; - - if (PB_ATYPE(type) == PB_ATYPE_STATIC && count > ((const pb_field_t *)PIC(iter->pos))->array_size) - { - /* Protect against corrupted _count fields */ - count = ((const pb_field_t *)PIC(iter->pos))->array_size; - } - } - - if (pItem) - { - while (count--) - { - pb_release((const pb_field_t*)((const pb_field_t *)PIC(iter->pos))->ptr, pItem); - pItem = (char*)pItem + ((const pb_field_t *)PIC(iter->pos))->data_size; - } - } + } + + if (PB_ATYPE(type) == PB_ATYPE_POINTER) { + if (PB_HTYPE(type) == PB_HTYPE_REPEATED && + (PB_LTYPE(type) == PB_LTYPE_STRING || + PB_LTYPE(type) == PB_LTYPE_BYTES)) { + /* Release entries in repeated string or bytes array */ + void **pItem = *(void ***)field->pField; + pb_size_t count = *(pb_size_t *)field->pSize; + while (count--) { + pb_free(*pItem); + *pItem++ = NULL; + } } - - if (PB_ATYPE(type) == PB_ATYPE_POINTER) - { - if (PB_HTYPE(type) == PB_HTYPE_REPEATED && - (PB_LTYPE(type) == PB_LTYPE_STRING || - PB_LTYPE(type) == PB_LTYPE_BYTES)) - { - /* Release entries in repeated string or bytes array */ - void **pItem = *(void***)iter->pData; - pb_size_t count = *(pb_size_t*)iter->pSize; - while (count--) - { - pb_free(*pItem); - *pItem++ = NULL; - } - } - - if (PB_HTYPE(type) == PB_HTYPE_REPEATED) - { - /* We are going to release the array, so set the size to 0 */ - *(pb_size_t*)iter->pSize = 0; - } - - /* Release main item */ - pb_free(*(void**)iter->pData); - *(void**)iter->pData = NULL; + + if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { + /* We are going to release the array, so set the size to 0 */ + *(pb_size_t *)field->pSize = 0; } + + /* Release main pointer */ + pb_free(*(void **)field->pField); + *(void **)field->pField = NULL; + } } -void pb_release(const pb_field_t fields[], void *dest_struct) -{ - pb_field_iter_t iter; - - if (!dest_struct) - return; /* Ignore NULL pointers, similar to free() */ - - if (!pb_field_iter_begin(&iter, fields, dest_struct)) - return; /* Empty message type */ - - do - { - pb_release_single_field(&iter); - } while (pb_field_iter_next(&iter)); +void pb_release(const pb_msgdesc_t *fields, void *dest_struct) { + pb_field_iter_t iter; + + if (!dest_struct) + return; /* Ignore NULL pointers, similar to free() */ + + if (!pb_field_iter_begin(&iter, fields, dest_struct)) + return; /* Empty message type */ + + do { + pb_release_single_field(&iter); + } while (pb_field_iter_next(&iter)); } #endif /* Field decoders */ -bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) -{ - pb_uint64_t value; - if (!pb_decode_varint(stream, &value)) - return false; - - if (value & 1) - *dest = (pb_int64_t)(~(value >> 1)); - else - *dest = (pb_int64_t)(value >> 1); - - return true; +bool pb_decode_bool(pb_istream_t *stream, bool *dest) { + uint32_t value; + if (!pb_decode_varint32(stream, &value)) + return false; + + *(bool *)dest = (value != 0); + return true; +} + +bool pb_decode_svarint(pb_istream_t *stream, pb_int64_t *dest) { + pb_uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + + if (value & 1) + *dest = (pb_int64_t)(~(value >> 1)); + else + *dest = (pb_int64_t)(value >> 1); + + return true; } -bool pb_decode_fixed32(pb_istream_t *stream, void *dest) -{ +bool pb_decode_fixed32(pb_istream_t *stream, void *dest) { + union { + uint32_t fixed32; pb_byte_t bytes[4]; + } u; - if (!pb_read(stream, bytes, 4)) - return false; - - *(uint32_t*)dest = ((uint32_t)bytes[0] << 0) | - ((uint32_t)bytes[1] << 8) | - ((uint32_t)bytes[2] << 16) | - ((uint32_t)bytes[3] << 24); - return true; + if (!pb_read(stream, u.bytes, 4)) + return false; + +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint32_t *)dest = u.fixed32; +#else + *(uint32_t *)dest = + ((uint32_t)u.bytes[0] << 0) | ((uint32_t)u.bytes[1] << 8) | + ((uint32_t)u.bytes[2] << 16) | ((uint32_t)u.bytes[3] << 24); +#endif + return true; } #ifndef PB_WITHOUT_64BIT -bool pb_decode_fixed64(pb_istream_t *stream, void *dest) -{ +bool pb_decode_fixed64(pb_istream_t *stream, void *dest) { + union { + uint64_t fixed64; pb_byte_t bytes[8]; + } u; - if (!pb_read(stream, bytes, 8)) - return false; - - *(uint64_t*)dest = ((uint64_t)bytes[0] << 0) | - ((uint64_t)bytes[1] << 8) | - ((uint64_t)bytes[2] << 16) | - ((uint64_t)bytes[3] << 24) | - ((uint64_t)bytes[4] << 32) | - ((uint64_t)bytes[5] << 40) | - ((uint64_t)bytes[6] << 48) | - ((uint64_t)bytes[7] << 56); - - return true; + if (!pb_read(stream, u.bytes, 8)) + return false; + +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN && CHAR_BIT == 8 + /* fast path - if we know that we're on little endian, assign directly */ + *(uint64_t *)dest = u.fixed64; +#else + *(uint64_t *)dest = + ((uint64_t)u.bytes[0] << 0) | ((uint64_t)u.bytes[1] << 8) | + ((uint64_t)u.bytes[2] << 16) | ((uint64_t)u.bytes[3] << 24) | + ((uint64_t)u.bytes[4] << 32) | ((uint64_t)u.bytes[5] << 40) | + ((uint64_t)u.bytes[6] << 48) | ((uint64_t)u.bytes[7] << 56); +#endif + return true; } #endif -static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - pb_uint64_t value=0; - pb_int64_t svalue=0; - pb_int64_t clamped=0; - if (!pb_decode_varint(stream, &value)) - return false; - - /* See issue 97: Google's C++ protobuf allows negative varint values to - * be cast as int32_t, instead of the int64_t that should be used when - * encoding. Previous nanopb versions had a bug in encoding. In order to - * not break decoding of such messages, we cast <=32 bit fields to - * int32_t first to get the sign correct. - */ - if (field->data_size == sizeof(pb_int64_t)) - svalue = (pb_int64_t)value; - else - svalue = (int32_t)value; - - /* Cast to the proper field size, while checking for overflows */ - if (field->data_size == sizeof(pb_int64_t)) - clamped = *(pb_int64_t*)dest = svalue; - else if (field->data_size == sizeof(int32_t)) - clamped = *(int32_t*)dest = (int32_t)svalue; - else if (field->data_size == sizeof(int_least16_t)) - clamped = *(int_least16_t*)dest = (int_least16_t)svalue; - else if (field->data_size == sizeof(int_least8_t)) - clamped = *(int_least8_t*)dest = (int_least8_t)svalue; - else - PB_RETURN_ERROR(stream, "invalid data_size"); - if (clamped != svalue) - PB_RETURN_ERROR(stream, "integer too large"); - - return true; +static bool checkreturn pb_dec_bool(pb_istream_t *stream, + const pb_field_iter_t *field) { + return pb_decode_bool(stream, (bool *)field->pData); } -static bool checkreturn pb_dec_uvarint(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - pb_uint64_t value = 0, clamped = 0; +static bool checkreturn pb_dec_varint(pb_istream_t *stream, + const pb_field_iter_t *field) { + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) { + pb_uint64_t value, clamped; if (!pb_decode_varint(stream, &value)) - return false; - + return false; + /* Cast to the proper field size, while checking for overflows */ if (field->data_size == sizeof(pb_uint64_t)) - clamped = *(pb_uint64_t*)dest = value; + clamped = *(pb_uint64_t *)field->pData = value; else if (field->data_size == sizeof(uint32_t)) - clamped = *(uint32_t*)dest = (uint32_t)value; + clamped = *(uint32_t *)field->pData = (uint32_t)value; else if (field->data_size == sizeof(uint_least16_t)) - clamped = *(uint_least16_t*)dest = (uint_least16_t)value; + clamped = *(uint_least16_t *)field->pData = (uint_least16_t)value; else if (field->data_size == sizeof(uint_least8_t)) - clamped = *(uint_least8_t*)dest = (uint_least8_t)value; + clamped = *(uint_least8_t *)field->pData = (uint_least8_t)value; else - PB_RETURN_ERROR(stream, "invalid data_size"); - + PB_RETURN_ERROR(stream, "invalid data_size"); + if (clamped != value) - PB_RETURN_ERROR(stream, "integer too large"); + PB_RETURN_ERROR(stream, "integer too large"); return true; -} + } else { + pb_uint64_t value; + pb_int64_t svalue; + pb_int64_t clamped; -static bool checkreturn pb_dec_svarint(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - pb_int64_t value, clamped; - if (!pb_decode_svarint(stream, &value)) + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) { + if (!pb_decode_svarint(stream, &svalue)) + return false; + } else { + if (!pb_decode_varint(stream, &value)) return false; - + + /* See issue 97: Google's C++ protobuf allows negative varint values to + * be cast as int32_t, instead of the int64_t that should be used when + * encoding. Previous nanopb versions had a bug in encoding. In order to + * not break decoding of such messages, we cast <=32 bit fields to + * int32_t first to get the sign correct. + */ + if (field->data_size == sizeof(pb_int64_t)) + svalue = (pb_int64_t)value; + else + svalue = (int32_t)value; + } + /* Cast to the proper field size, while checking for overflows */ if (field->data_size == sizeof(pb_int64_t)) - clamped = *(pb_int64_t*)dest = value; + clamped = *(pb_int64_t *)field->pData = svalue; else if (field->data_size == sizeof(int32_t)) - clamped = *(int32_t*)dest = (int32_t)value; + clamped = *(int32_t *)field->pData = (int32_t)svalue; else if (field->data_size == sizeof(int_least16_t)) - clamped = *(int_least16_t*)dest = (int_least16_t)value; + clamped = *(int_least16_t *)field->pData = (int_least16_t)svalue; else if (field->data_size == sizeof(int_least8_t)) - clamped = *(int_least8_t*)dest = (int_least8_t)value; + clamped = *(int_least8_t *)field->pData = (int_least8_t)svalue; else - PB_RETURN_ERROR(stream, "invalid data_size"); + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (clamped != svalue) + PB_RETURN_ERROR(stream, "integer too large"); - if (clamped != value) - PB_RETURN_ERROR(stream, "integer too large"); - return true; + } } -static bool checkreturn pb_dec_fixed32(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - PB_UNUSED(field); - return pb_decode_fixed32(stream, dest); -} +static bool checkreturn pb_dec_fixed(pb_istream_t *stream, + const pb_field_iter_t *field) { +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float) && + PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { + return pb_decode_double_as_float(stream, (float *)field->pData); + } +#endif -static bool checkreturn pb_dec_fixed64(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - PB_UNUSED(field); + if (field->data_size == sizeof(uint32_t)) { + return pb_decode_fixed32(stream, field->pData); + } #ifndef PB_WITHOUT_64BIT - return pb_decode_fixed64(stream, dest); -#else - PB_UNUSED(dest); - PB_RETURN_ERROR(stream, "no 64bit support"); + else if (field->data_size == sizeof(uint64_t)) { + return pb_decode_fixed64(stream, field->pData); + } #endif + else { + PB_RETURN_ERROR(stream, "invalid data_size"); + } } -static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - uint32_t size; - size_t alloc_size; - pb_bytes_array_t *bdest; - - if (!pb_decode_varint32(stream, &size)) - return false; - - if (size > PB_SIZE_MAX) - PB_RETURN_ERROR(stream, "bytes overflow"); - - alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); - if (size > alloc_size) - PB_RETURN_ERROR(stream, "size too large"); - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { +static bool checkreturn pb_dec_bytes(pb_istream_t *stream, + const pb_field_iter_t *field) { + uint32_t size; + size_t alloc_size; + pb_bytes_array_t *dest; + + if (!pb_decode_varint32(stream, &size)) + return false; + + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); + + alloc_size = PB_BYTES_ARRAY_T_ALLOCSIZE(size); + if (size > alloc_size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { #ifndef PB_ENABLE_MALLOC - PB_RETURN_ERROR(stream, "no malloc support"); + PB_RETURN_ERROR(stream, "no malloc support"); #else - if (!allocate_field(stream, dest, alloc_size, 1)) - return false; - bdest = *(pb_bytes_array_t**)dest; + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_bytes_array_t **)field->pData; #endif - } - else - { - if (alloc_size > field->data_size) - PB_RETURN_ERROR(stream, "bytes overflow"); - bdest = (pb_bytes_array_t*)dest; - } - - bdest->size = (pb_size_t)size; - return pb_read(stream, bdest->bytes, size); + } else { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "bytes overflow"); + dest = (pb_bytes_array_t *)field->pData; + } + + dest->size = (pb_size_t)size; + return pb_read(stream, dest->bytes, (size_t)size); } -static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - uint32_t size; - size_t alloc_size; - bool status; - if (!pb_decode_varint32(stream, &size)) - return false; - - /* Space for null terminator */ - alloc_size = size + 1; - - if (alloc_size < size) - PB_RETURN_ERROR(stream, "size too large"); - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { +static bool checkreturn pb_dec_string(pb_istream_t *stream, + const pb_field_iter_t *field) { + uint32_t size; + size_t alloc_size; + pb_byte_t *dest = (pb_byte_t *)field->pData; + + if (!pb_decode_varint32(stream, &size)) + return false; + + /* Space for null terminator */ + alloc_size = (size_t)(size + 1); + + if (alloc_size < size) + PB_RETURN_ERROR(stream, "size too large"); + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { #ifndef PB_ENABLE_MALLOC - PB_RETURN_ERROR(stream, "no malloc support"); + PB_RETURN_ERROR(stream, "no malloc support"); #else - if (!allocate_field(stream, dest, alloc_size, 1)) - return false; - dest = *(void**)dest; + if (!allocate_field(stream, field->pData, alloc_size, 1)) + return false; + dest = *(pb_byte_t **)field->pData; #endif - } - else - { - if (alloc_size > field->data_size) - PB_RETURN_ERROR(stream, "string overflow"); - } - - status = pb_read(stream, (pb_byte_t*)dest, size); - *((pb_byte_t*)dest + size) = 0; - return status; + } else { + if (alloc_size > field->data_size) + PB_RETURN_ERROR(stream, "string overflow"); + } + + dest[size] = 0; + + if (!pb_read(stream, dest, (size_t)size)) + return false; + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8((const char *)dest)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return true; } -static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - bool status; - pb_istream_t substream; - const pb_field_t* submsg_fields = (const pb_field_t*)PIC(field->ptr); - - if (!pb_make_string_substream(stream, &substream)) - return false; - - if (field->ptr == NULL) - PB_RETURN_ERROR(stream, "invalid field descriptor"); - - /* New array entries need to be initialized, while required and optional - * submessages have already been initialized in the top-level pb_decode. */ - if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) - { - status = pb_decode(&substream, submsg_fields, dest); +static bool checkreturn pb_dec_submessage(pb_istream_t *stream, + const pb_field_iter_t *field) { + bool status = true; + pb_istream_t substream; + + if (!pb_make_string_substream(stream, &substream)) + return false; + + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); + + /* New array entries need to be initialized, while required and optional + * submessages have already been initialized in the top-level pb_decode. */ + if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED || + PB_HTYPE(field->type) == PB_HTYPE_ONEOF) { + pb_field_iter_t submsg_iter; + if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData)) { + if (!pb_message_set_to_defaults(&submsg_iter)) + PB_RETURN_ERROR(stream, "failed to set defaults"); } - else - { - status = pb_decode_noinit(&substream, submsg_fields, dest); + } + + /* Submessages can have a separate message-level callback that is called + * before decoding the message. Typically it is used to set callback fields + * inside oneofs. */ + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t *)field->pSize - 1; + if (callback->funcs.decode) { + status = callback->funcs.decode(&substream, field, &callback->arg); } - if (!pb_close_string_substream(stream, &substream)) - return false; - return status; + } + + /* Now decode the submessage contents */ + if (status) { + status = pb_decode_noinit(&substream, field->submsg_desc, field->pData); + } + + if (!pb_close_string_substream(stream, &substream)) + return false; + + return status; } -static bool checkreturn pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_t *field, void *dest) -{ - uint32_t size; +static bool checkreturn +pb_dec_fixed_length_bytes(pb_istream_t *stream, const pb_field_iter_t *field) { + uint32_t size; - if (!pb_decode_varint32(stream, &size)) - return false; + if (!pb_decode_varint32(stream, &size)) + return false; - if (size > PB_SIZE_MAX) - PB_RETURN_ERROR(stream, "bytes overflow"); + if (size > PB_SIZE_MAX) + PB_RETURN_ERROR(stream, "bytes overflow"); - if (size == 0) - { - /* As a special case, treat empty bytes string as all zeros for fixed_length_bytes. */ - memset(dest, 0, field->data_size); - return true; - } + if (size == 0) { + /* As a special case, treat empty bytes string as all zeros for + * fixed_length_bytes. */ + memset(field->pData, 0, (size_t)field->data_size); + return true; + } + + if (size != field->data_size) + PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); + + return pb_read(stream, (pb_byte_t *)field->pData, (size_t)field->data_size); +} - if (size != field->data_size) - PB_RETURN_ERROR(stream, "incorrect fixed length bytes size"); +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest) { + uint8_t sign; + int exponent; + uint32_t mantissa; + uint64_t value; + union { + float f; + uint32_t i; + } out; + + if (!pb_decode_fixed64(stream, &value)) + return false; - return pb_read(stream, (pb_byte_t*)dest, field->data_size); + /* Decompose input value */ + sign = (uint8_t)((value >> 63) & 1); + exponent = (int)((value >> 52) & 0x7FF) - 1023; + mantissa = (value >> 28) & 0xFFFFFF; /* Highest 24 bits */ + + /* Figure if value is in range representable by floats. */ + if (exponent == 1024) { + /* Special value */ + exponent = 128; + } else if (exponent > 127) { + /* Too large, convert to infinity */ + exponent = 128; + mantissa = 0; + } else if (exponent < -150) { + /* Too small, convert to zero */ + exponent = -127; + mantissa = 0; + } else if (exponent < -126) { + /* Denormalized */ + mantissa |= 0x1000000; + mantissa >>= (-126 - exponent); + exponent = -127; + } + + /* Round off mantissa */ + mantissa = (mantissa + 1) >> 1; + + /* Check if mantissa went over 2.0 */ + if (mantissa & 0x800000) { + exponent += 1; + mantissa &= 0x7FFFFF; + mantissa >>= 1; + } + + /* Combine fields */ + out.i = mantissa; + out.i |= (uint32_t)(exponent + 127) << 23; + out.i |= (uint32_t)sign << 31; + + *dest = out.f; + return true; } +#endif diff --git a/src/nanopb/pb_decode.h b/src/nanopb/pb_decode.h index 5fcc201b..f5f266b3 100644 --- a/src/nanopb/pb_decode.h +++ b/src/nanopb/pb_decode.h @@ -12,14 +12,10 @@ extern "C" { #endif -/* Tracks call stack when instrumentation is enabled - * Should be set to 0 when instantiating pb_istream_t*/ -extern int G_depth; - /* Structure for defining custom input streams. You will need to provide * a callback function to read the bytes from your storage, which can be * for example a file or a network socket. - * + * * The callback must conform to these rules: * * 1) Return false on IO errors. This will cause decoding to abort. @@ -29,85 +25,96 @@ extern int G_depth; * is different than from the main stream. Don't use bytes_left to compute * any pointers. */ -struct pb_istream_s -{ +struct pb_istream_s { #ifdef PB_BUFFER_ONLY - /* Callback pointer is not used in buffer-only configuration. - * Having an int pointer here allows binary compatibility but - * gives an error if someone tries to assign callback function. - */ - int *callback; + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + */ + int *callback; #else - bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); + bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count); #endif - void *state; /* Free field for use by callback implementation */ - size_t bytes_left; - + void *state; /* Free field for use by callback implementation */ + size_t bytes_left; + #ifndef PB_NO_ERRMSG - const char *errmsg; + const char *errmsg; #endif }; +#ifndef PB_NO_ERRMSG +#define PB_ISTREAM_EMPTY \ + { 0, 0, 0, 0 } +#else +#define PB_ISTREAM_EMPTY \ + { 0, 0, 0 } +#endif /*************************** * Main decoding functions * ***************************/ - -/* Decode a single protocol buffers message from input stream into a C structure. - * Returns true on success, false on any failure. - * The actual struct pointed to by dest must match the description in fields. - * Callback fields of the destination structure must be initialized by caller. - * All other fields will be initialized by this function. + +/* Decode a single protocol buffers message from input stream into a C + * structure. Returns true on success, false on any failure. The actual struct + * pointed to by dest must match the description in fields. Callback fields of + * the destination structure must be initialized by caller. All other fields + * will be initialized by this function. * * Example usage: * MyMessage msg = {}; * uint8_t buffer[64]; * pb_istream_t stream; - * + * * // ... read some data into buffer ... * * stream = pb_istream_from_buffer(buffer, count); * pb_decode(&stream, MyMessage_fields, &msg); */ -bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); +bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, + void *dest_struct); -/* Same as pb_decode, except does not initialize the destination structure - * to default values. This is slightly faster if you need no default values - * and just do memset(struct, 0, sizeof(struct)) yourself. +/* Extended version of pb_decode, with several options to control + * the decoding process: * - * This can also be used for 'merging' two messages, i.e. update only the - * fields that exist in the new message. + * PB_DECODE_NOINIT: Do not initialize the fields to default values. + * This is slightly faster if you do not need the + * default values and instead initialize the structure to 0 using e.g. memset(). + * This can also be used for merging two messages, i.e. combine already existing + * data with new values. * - * Note: If this function returns with an error, it will not release any - * dynamically allocated fields. You will need to call pb_release() yourself. - */ -bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); - -/* Same as pb_decode, except expects the stream to start with the message size - * encoded as varint. Corresponds to parseDelimitedFrom() in Google's - * protobuf API. - */ -bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); - -/* Same as pb_decode_delimited, except that it does not initialize the destination structure. - * See pb_decode_noinit - */ -bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); - -/* Same as pb_decode, except allows the message to be terminated with a null byte. - * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour - * is not supported in most other protobuf implementations, so pb_decode_delimited() - * is a better option for compatibility. + * PB_DECODE_DELIMITED: Input message starts with the message size as + * varint. Corresponds to parseDelimitedFrom() in Google's protobuf API. + * + * PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This + * allows reading null terminated messages. NOTE: Until nanopb-0.4.0, + * pb_decode() also allows null-termination. This behaviour is not supported in + * most other protobuf implementations, so + * PB_DECODE_DELIMITED is a better option for compatibility. + * + * Multiple flags can be combined with bitwise or (| operator) */ -bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct); +#define PB_DECODE_NOINIT 0x01U +#define PB_DECODE_DELIMITED 0x02U +#define PB_DECODE_NULLTERMINATED 0x04U +bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, + void *dest_struct, unsigned int flags); + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_decode_noinit(s, f, d) pb_decode_ex(s, f, d, PB_DECODE_NOINIT) +#define pb_decode_delimited(s, f, d) pb_decode_ex(s, f, d, PB_DECODE_DELIMITED) +#define pb_decode_delimited_noinit(s, f, d) \ + pb_decode_ex(s, f, d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT) +#define pb_decode_nullterminated(s, f, d) \ + pb_decode_ex(s, f, d, PB_DECODE_NULLTERMINATED) #ifdef PB_ENABLE_MALLOC -/* Release any allocated pointer fields. If you use dynamic allocation, you should - * call this for any successfully decoded message when you are done with it. If - * pb_decode() returns with an error, the message is already released. +/* Release any allocated pointer fields. If you use dynamic allocation, you + * should call this for any successfully decoded message when you are done with + * it. If pb_decode() returns with an error, the message is already released. */ -void pb_release(const pb_field_t fields[], void *dest_struct); +void pb_release(const pb_msgdesc_t *fields, void *dest_struct); #endif /************************************** @@ -132,24 +139,27 @@ bool pb_read(pb_istream_t *stream, pb_byte_t *buf, size_t count); /* Decode the tag for the next field in the stream. Gives the wire type and * field tag. At end of the message, returns false and sets eof to true. */ -bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, uint32_t *tag, bool *eof); +bool pb_decode_tag(pb_istream_t *stream, pb_wire_type_t *wire_type, + uint32_t *tag, bool *eof); /* Skip the field payload data, given the wire type. */ bool pb_skip_field(pb_istream_t *stream, pb_wire_type_t wire_type); -/* Decode an integer in the varint format. This works for bool, enum, int32, +/* Decode an integer in the varint format. This works for enum, int32, * int64, uint32 and uint64 field types. */ #ifndef PB_WITHOUT_64BIT bool pb_decode_varint(pb_istream_t *stream, uint64_t *dest); #else #define pb_decode_varint pb_decode_varint32 #endif -// uint64_t val2; -/* Decode an integer in the varint format. This works for bool, enum, int32, +/* Decode an integer in the varint format. This works for enum, int32, * and uint32 field types. */ bool pb_decode_varint32(pb_istream_t *stream, uint32_t *dest); +/* Decode a bool value in varint format. */ +bool pb_decode_bool(pb_istream_t *stream, bool *dest); + /* Decode an integer in the zig-zagged svarint format. This works for sint32 * and sint64. */ #ifndef PB_WITHOUT_64BIT @@ -168,6 +178,11 @@ bool pb_decode_fixed32(pb_istream_t *stream, void *dest); bool pb_decode_fixed64(pb_istream_t *stream, void *dest); #endif +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Decode a double value into float variable. */ +bool pb_decode_double_as_float(pb_istream_t *stream, float *dest); +#endif + /* Make a limited-length substream for reading a PB_WT_STRING field. */ bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream); bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream); diff --git a/src/nanopb/pb_encode.c b/src/nanopb/pb_encode.c index 41d3c8ae..f7a2f380 100644 --- a/src/nanopb/pb_encode.c +++ b/src/nanopb/pb_encode.c @@ -7,42 +7,53 @@ #include "pb_encode.h" #include "pb_common.h" -#ifdef OS_IO_SEPROXYHAL -#include "os.h" -#else -#define PIC(x) x -#endif - /* Use the GCC warn_unused_result attribute to check that all return values * are propagated correctly. On other compilers and gcc before 3.4.0 just * ignore the annotation. */ -#if !defined(__GNUC__) || ( __GNUC__ < 3) || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) - #define checkreturn +#if !defined(__GNUC__) || (__GNUC__ < 3) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +#define checkreturn #else - #define checkreturn __attribute__((warn_unused_result)) +#define checkreturn __attribute__((warn_unused_result)) #endif /************************************** * Declarations internal to this file * **************************************/ -typedef bool (*pb_encoder_t)(pb_ostream_t *stream, const pb_field_t *field, const void *src) checkreturn; - -static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); -static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, const void *pData, size_t count, pb_encoder_t func); -static bool checkreturn encode_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); -static bool checkreturn default_extension_encoder(pb_ostream_t *stream, const pb_extension_t *extension); -static bool checkreturn encode_extension_field(pb_ostream_t *stream, const pb_field_t *field, const void *pData); +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, + size_t count); +static bool checkreturn encode_array(pb_ostream_t *stream, + pb_field_iter_t *field); +static bool checkreturn +pb_check_proto3_default_value(const pb_field_iter_t *field); +static bool checkreturn encode_basic_field(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn encode_callback_field(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn encode_field(pb_ostream_t *stream, + pb_field_iter_t *field); +static bool checkreturn encode_extension_field(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn default_extension_encoder( + pb_ostream_t *stream, const pb_extension_t *extension); static void *pb_const_cast(const void *p); -static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src); -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src); +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, + uint32_t high); +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_string(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, + const pb_field_iter_t *field); +static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, + const pb_field_iter_t *field); #ifdef PB_WITHOUT_64BIT #define pb_int64_t int32_t @@ -52,780 +63,825 @@ static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb #define pb_uint64_t uint64_t #endif -/* --- Function pointers to field encoders --- - * Order in the array must match pb_action_t LTYPE numbering. - */ -static const pb_encoder_t PB_ENCODERS[PB_LTYPES_COUNT] = { - &pb_enc_varint, - &pb_enc_uvarint, - &pb_enc_svarint, - &pb_enc_fixed32, - &pb_enc_fixed64, - - &pb_enc_bytes, - &pb_enc_string, - &pb_enc_submessage, - NULL, /* extensions */ - &pb_enc_fixed_length_bytes -}; - /******************************* * pb_ostream_t implementation * *******************************/ -static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) -{ - size_t i; - pb_byte_t *dest = (pb_byte_t*)stream->state; - stream->state = dest + count; - - for (i = 0; i < count; i++) - dest[i] = buf[i]; - - return true; +static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, + size_t count) { + size_t i; + pb_byte_t *dest = (pb_byte_t *)stream->state; + stream->state = dest + count; + + for (i = 0; i < count; i++) + dest[i] = buf[i]; + + return true; } -pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) -{ - pb_ostream_t stream; +pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize) { + pb_ostream_t stream; #ifdef PB_BUFFER_ONLY - stream.callback = (void*)1; /* Just a marker value */ + stream.callback = (void *)1; /* Just a marker value */ #else - stream.callback = &buf_write; + stream.callback = &buf_write; #endif - stream.state = buf; - stream.max_size = bufsize; - stream.bytes_written = 0; + stream.state = buf; + stream.max_size = bufsize; + stream.bytes_written = 0; #ifndef PB_NO_ERRMSG - stream.errmsg = NULL; + stream.errmsg = NULL; #endif - return stream; + return stream; } -bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) -{ - if (stream->callback != NULL) - { - if (stream->bytes_written + count > stream->max_size) - PB_RETURN_ERROR(stream, "stream full"); +bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, + size_t count) { + if (count > 0 && stream->callback != NULL) { + if (stream->bytes_written + count > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); #ifdef PB_BUFFER_ONLY - if (!buf_write(stream, buf, count)) - PB_RETURN_ERROR(stream, "io error"); -#else - if (!stream->callback(stream, buf, count)) - PB_RETURN_ERROR(stream, "io error"); + if (!buf_write(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); +#else + if (!stream->callback(stream, buf, count)) + PB_RETURN_ERROR(stream, "io error"); #endif - } - - stream->bytes_written += count; - return true; + } + + stream->bytes_written += count; + return true; } /************************* * Encode a single field * *************************/ +/* Read a bool value without causing undefined behavior even if the value + * is invalid. See issue #434 and + * https://stackoverflow.com/questions/27661768/weird-results-for-conditional + */ +static bool safe_read_bool(const void *pSize) { + const char *p = (const char *)pSize; + size_t i; + for (i = 0; i < sizeof(bool); i++) { + if (p[i] != 0) + return true; + } + return false; +} + /* Encode a static array. Handles the size calculations and possible packing. */ -static bool checkreturn encode_array(pb_ostream_t *stream, const pb_field_t *field, - const void *pData, size_t count, pb_encoder_t func) -{ - size_t i; - const void *p; - size_t size; - - if (count == 0) - return true; +static bool checkreturn encode_array(pb_ostream_t *stream, + pb_field_iter_t *field) { + pb_size_t i; + pb_size_t count; +#ifndef PB_ENCODE_ARRAYS_UNPACKED + size_t size; +#endif - if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) - PB_RETURN_ERROR(stream, "array max size exceeded"); - - /* We always pack arrays if the datatype allows it. */ - if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) - { - if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) - return false; - - /* Determine the total size of packed array. */ - if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) - { - size = 4 * count; - } - else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) - { - size = 8 * count; - } - else - { - pb_ostream_t sizestream = PB_OSTREAM_SIZING; - p = pData; - for (i = 0; i < count; i++) - { - if (!func(&sizestream, field, p)) - return false; - p = (const char*)p + field->data_size; - } - size = sizestream.bytes_written; - } - - if (!pb_encode_varint(stream, (pb_uint64_t)size)) - return false; - - if (stream->callback == NULL) - return pb_write(stream, NULL, size); /* Just sizing.. */ - - /* Write the data */ - p = pData; - for (i = 0; i < count; i++) - { - if (!func(stream, field, p)) - return false; - p = (const char*)p + field->data_size; - } - } - else - { - p = pData; - for (i = 0; i < count; i++) - { - if (!pb_encode_tag_for_field(stream, field)) - return false; - - /* Normally the data is stored directly in the array entries, but - * for pointer-type string and bytes fields, the array entries are - * actually pointers themselves also. So we have to dereference once - * more to get to the actual data. */ - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && - (PB_LTYPE(field->type) == PB_LTYPE_STRING || - PB_LTYPE(field->type) == PB_LTYPE_BYTES)) - { - if (!func(stream, field, *(const void* const*)p)) - return false; - } - else - { - if (!func(stream, field, p)) - return false; - } - p = (const char*)p + field->data_size; - } - } - - return true; -} + count = *(pb_size_t *)field->pSize; -/* In proto3, all fields are optional and are only encoded if their value is "non-zero". - * This function implements the check for the zero value. */ -static bool pb_check_proto3_default_value(const pb_field_t *field, const void *pData) -{ - pb_type_t type = field->type; - const void *pSize = (const char*)pData + field->size_offset; + if (count == 0) + return true; - if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) - { - /* Required proto2 fields inside proto3 submessage, pretty rare case */ - return false; + if (PB_ATYPE(field->type) != PB_ATYPE_POINTER && count > field->array_size) + PB_RETURN_ERROR(stream, "array max size exceeded"); + +#ifndef PB_ENCODE_ARRAYS_UNPACKED + /* We always pack arrays if the datatype allows it. */ + if (PB_LTYPE(field->type) <= PB_LTYPE_LAST_PACKABLE) { + if (!pb_encode_tag(stream, PB_WT_STRING, field->tag)) + return false; + + /* Determine the total size of packed array. */ + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32) { + size = 4 * (size_t)count; + } else if (PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { + size = 8 * (size_t)count; + } else { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + void *pData_orig = field->pData; + for (i = 0; i < count; i++) { + if (!pb_enc_varint(&sizestream, field)) + PB_RETURN_ERROR(stream, PB_GET_ERROR(&sizestream)); + field->pData = (char *)field->pData + field->data_size; + } + field->pData = pData_orig; + size = sizestream.bytes_written; } - else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) - { - /* Repeated fields inside proto3 submessage: present if count != 0 */ - return *(const pb_size_t*)pSize == 0; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing.. */ + + /* Write the data */ + for (i = 0; i < count; i++) { + if (PB_LTYPE(field->type) == PB_LTYPE_FIXED32 || + PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { + if (!pb_enc_fixed(stream, field)) + return false; + } else { + if (!pb_enc_varint(stream, field)) + return false; + } + + field->pData = (char *)field->pData + field->data_size; } - else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) - { - /* Oneof fields */ - return *(const pb_size_t*)pSize == 0; + } else /* Unpacked fields */ +#endif + { + for (i = 0; i < count; i++) { + /* Normally the data is stored directly in the array entries, but + * for pointer-type string and bytes fields, the array entries are + * actually pointers themselves also. So we have to dereference once + * more to get to the actual data. */ + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER && + (PB_LTYPE(field->type) == PB_LTYPE_STRING || + PB_LTYPE(field->type) == PB_LTYPE_BYTES)) { + bool status; + void *pData_orig = field->pData; + field->pData = *(void *const *)field->pData; + + if (!field->pData) { + /* Null pointer in array is treated as empty string / bytes */ + status = pb_encode_tag_for_field(stream, field) && + pb_encode_varint(stream, 0); + } else { + status = encode_basic_field(stream, field); + } + + field->pData = pData_orig; + + if (!status) + return false; + } else { + if (!encode_basic_field(stream, field)) + return false; + } + field->pData = (char *)field->pData + field->data_size; } - else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->size_offset) - { - /* Proto2 optional fields inside proto3 submessage */ - return *(const bool*)pSize == false; + } + + return true; +} + +/* In proto3, all fields are optional and are only encoded if their value is + * "non-zero". This function implements the check for the zero value. */ +static bool checkreturn +pb_check_proto3_default_value(const pb_field_iter_t *field) { + pb_type_t type = field->type; + + if (PB_ATYPE(type) == PB_ATYPE_STATIC) { + if (PB_HTYPE(type) == PB_HTYPE_REQUIRED) { + /* Required proto2 fields inside proto3 submessage, pretty rare case */ + return false; + } else if (PB_HTYPE(type) == PB_HTYPE_REPEATED) { + /* Repeated fields inside proto3 submessage: present if count != 0 */ + return *(const pb_size_t *)field->pSize == 0; + } else if (PB_HTYPE(type) == PB_HTYPE_ONEOF) { + /* Oneof fields */ + return *(const pb_size_t *)field->pSize == 0; + } else if (PB_HTYPE(type) == PB_HTYPE_OPTIONAL && field->pSize != NULL) { + /* Proto2 optional fields inside proto3 message, or proto3 + * submessage fields. */ + return safe_read_bool(field->pSize) == false; } /* Rest is proto3 singular fields */ - - if (PB_ATYPE(type) == PB_ATYPE_STATIC) - { - if (PB_LTYPE(type) == PB_LTYPE_BYTES) - { - const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)pData; - return bytes->size == 0; - } - else if (PB_LTYPE(type) == PB_LTYPE_STRING) - { - return *(const char*)pData == '\0'; - } - else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) - { - /* Fixed length bytes is only empty if its length is fixed - * as 0. Which would be pretty strange, but we can check - * it anyway. */ - return field->data_size == 0; - } - else if (PB_LTYPE(type) == PB_LTYPE_SUBMESSAGE) - { - /* Check all fields in the submessage to find if any of them - * are non-zero. The comparison cannot be done byte-per-byte - * because the C struct may contain padding bytes that must - * be skipped. - */ - pb_field_iter_t iter; - if (pb_field_iter_begin(&iter, (const pb_field_t*)field->ptr, pb_const_cast(pData))) - { - do - { - if (!pb_check_proto3_default_value(iter.pos, iter.pData)) - { - return false; - } - } while (pb_field_iter_next(&iter)); - } - return true; - } + if (PB_LTYPE(type) == PB_LTYPE_BYTES) { + const pb_bytes_array_t *bytes = (const pb_bytes_array_t *)field->pData; + return bytes->size == 0; + } else if (PB_LTYPE(type) == PB_LTYPE_STRING) { + return *(const char *)field->pData == '\0'; + } else if (PB_LTYPE(type) == PB_LTYPE_FIXED_LENGTH_BYTES) { + /* Fixed length bytes is only empty if its length is fixed + * as 0. Which would be pretty strange, but we can check + * it anyway. */ + return field->data_size == 0; + } else if (PB_LTYPE_IS_SUBMSG(type)) { + /* Check all fields in the submessage to find if any of them + * are non-zero. The comparison cannot be done byte-per-byte + * because the C struct may contain padding bytes that must + * be skipped. Note that usually proto3 submessages have + * a separate has_field that is checked earlier in this if. + */ + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, field->submsg_desc, field->pData)) { + do { + if (!pb_check_proto3_default_value(&iter)) { + return false; + } + } while (pb_field_iter_next(&iter)); + } + return true; } - - { - /* Catch-all branch that does byte-per-byte comparison for zero value. - * - * This is for all pointer fields, and for static PB_LTYPE_VARINT, - * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also - * callback fields. These all have integer or pointer value which - * can be compared with 0. - */ - pb_size_t i; - const char *p = (const char*)pData; - for (i = 0; i < field->data_size; i++) - { - if (p[i] != 0) - { - return false; - } - } - - return true; - } + } + + { + /* Catch-all branch that does byte-per-byte comparison for zero value. + * + * This is for all pointer fields, and for static PB_LTYPE_VARINT, + * UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also + * callback fields. These all have integer or pointer value which + * can be compared with 0. + */ + pb_size_t i; + const char *p = (const char *)field->pData; + for (i = 0; i < field->data_size; i++) { + if (p[i] != 0) { + return false; + } + } + + return true; + } } /* Encode a field with static or pointer allocation, i.e. one whose data * is available to the encoder directly. */ static bool checkreturn encode_basic_field(pb_ostream_t *stream, - const pb_field_t *field, const void *pData) -{ - pb_encoder_t func; - bool implicit_has; - const void *pSize = &implicit_has; - - func = PB_ENCODERS[PB_LTYPE(field->type)]; - - if (field->size_offset) - { - /* Static optional, repeated or oneof field */ - pSize = (const char*)pData + field->size_offset; - } - else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) - { - /* Proto3 style field, optional but without explicit has_ field. */ - implicit_has = !pb_check_proto3_default_value(field, pData); - } - else - { - /* Required field, always present */ - implicit_has = true; - } + const pb_field_iter_t *field) { + if (!field->pData) { + /* Missing pointer field */ + return true; + } - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { - /* pData is a pointer to the field, which contains pointer to - * the data. If the 2nd pointer is NULL, it is interpreted as if - * the has_field was false. - */ - pData = *(const void* const*)pData; - implicit_has = (pData != NULL); - } + if (!pb_encode_tag_for_field(stream, field)) + return false; - switch (PB_HTYPE(field->type)) - { - case PB_HTYPE_REQUIRED: - if (!pData) - PB_RETURN_ERROR(stream, "missing required field"); - if (!pb_encode_tag_for_field(stream, field)) - return false; - if (!((pb_encoder_t)PIC(func))(stream, field, pData)) - return false; - break; - - case PB_HTYPE_OPTIONAL: - if (*(const bool*)pSize) - { - if (!pb_encode_tag_for_field(stream, field)) - return false; - if (!((pb_encoder_t)PIC(func))(stream, field, pData)) - return false; - } - break; - - case PB_HTYPE_REPEATED: - if (!encode_array(stream, field, pData, *(const pb_size_t*)pSize, func)) - return false; - break; - - case PB_HTYPE_ONEOF: - if (*(const pb_size_t*)pSize == field->tag) - { - if (!pb_encode_tag_for_field(stream, field)) - return false; - - if (!((pb_encoder_t)PIC(func))(stream, field, pData)) - return false; - } - break; - - default: - PB_RETURN_ERROR(stream, "invalid field type"); - } - return true; + switch (PB_LTYPE(field->type)) { + case PB_LTYPE_BOOL: + return pb_enc_bool(stream, field); + + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + return pb_enc_varint(stream, field); + + case PB_LTYPE_FIXED32: + case PB_LTYPE_FIXED64: + return pb_enc_fixed(stream, field); + + case PB_LTYPE_BYTES: + return pb_enc_bytes(stream, field); + + case PB_LTYPE_STRING: + return pb_enc_string(stream, field); + + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + return pb_enc_submessage(stream, field); + + case PB_LTYPE_FIXED_LENGTH_BYTES: + return pb_enc_fixed_length_bytes(stream, field); + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } } /* Encode a field with callback semantics. This means that a user function is * called to provide and encode the actual data. */ static bool checkreturn encode_callback_field(pb_ostream_t *stream, - const pb_field_t *field, const void *pData) -{ - const pb_callback_t *callback = (const pb_callback_t*)pData; - -#ifdef PB_OLD_CALLBACK_STYLE - const void *arg = callback->arg; -#else - void * const *arg = &(callback->arg); -#endif - - if (callback->funcs.encode != NULL) - { - if (!callback->funcs.encode(stream, field, arg)) - PB_RETURN_ERROR(stream, "callback error"); - } - return true; + const pb_field_iter_t *field) { + if (field->descriptor->field_callback != NULL) { + if (!field->descriptor->field_callback(NULL, stream, field)) + PB_RETURN_ERROR(stream, "callback error"); + } + return true; } -/* Encode a single field of any callback or static type. */ +/* Encode a single field of any callback, pointer or static type. */ static bool checkreturn encode_field(pb_ostream_t *stream, - const pb_field_t *field, const void *pData) -{ - switch (PB_ATYPE(field->type)) - { - case PB_ATYPE_STATIC: - case PB_ATYPE_POINTER: - return encode_basic_field(stream, field, pData); - - case PB_ATYPE_CALLBACK: - return encode_callback_field(stream, field, pData); - - default: - PB_RETURN_ERROR(stream, "invalid field type"); + pb_field_iter_t *field) { + /* Check field presence */ + if (PB_HTYPE(field->type) == PB_HTYPE_ONEOF) { + if (*(const pb_size_t *)field->pSize != field->tag) { + /* Different type oneof field */ + return true; + } + } else if (PB_HTYPE(field->type) == PB_HTYPE_OPTIONAL) { + if (field->pSize) { + if (safe_read_bool(field->pSize) == false) { + /* Missing optional field */ + return true; + } + } else if (PB_ATYPE(field->type) == PB_ATYPE_STATIC) { + /* Proto3 singular field */ + if (pb_check_proto3_default_value(field)) + return true; } + } + + if (!field->pData) { + if (PB_HTYPE(field->type) == PB_HTYPE_REQUIRED) + PB_RETURN_ERROR(stream, "missing required field"); + + /* Pointer field set to NULL */ + return true; + } + + /* Then encode field contents */ + if (PB_ATYPE(field->type) == PB_ATYPE_CALLBACK) { + return encode_callback_field(stream, field); + } else if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED) { + return encode_array(stream, field); + } else { + return encode_basic_field(stream, field); + } } -/* Default handler for extension fields. Expects to have a pb_field_t - * pointer in the extension->type->arg field. */ -static bool checkreturn default_extension_encoder(pb_ostream_t *stream, - const pb_extension_t *extension) -{ - const pb_field_t *field = (const pb_field_t*)extension->type->arg; - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - { - /* For pointer extensions, the pointer is stored directly - * in the extension structure. This avoids having an extra - * indirection. */ - return encode_field(stream, field, &extension->dest); - } - else - { - return encode_field(stream, field, extension->dest); - } +/* Default handler for extension fields. Expects to have a pb_msgdesc_t + * pointer in the extension->type->arg field, pointing to a message with + * only one field in it. */ +static bool checkreturn default_extension_encoder( + pb_ostream_t *stream, const pb_extension_t *extension) { + pb_field_iter_t iter; + + if (!pb_field_iter_begin_extension( + &iter, (pb_extension_t *)pb_const_cast(extension))) + PB_RETURN_ERROR(stream, "invalid extension"); + + return encode_field(stream, &iter); } /* Walk through all the registered extensions and give them a chance * to encode themselves. */ static bool checkreturn encode_extension_field(pb_ostream_t *stream, - const pb_field_t *field, const void *pData) -{ - const pb_extension_t *extension = *(const pb_extension_t* const *)pData; - PB_UNUSED(field); - - while (extension) - { - bool status; - if (extension->type->encode) - status = extension->type->encode(stream, extension); - else - status = default_extension_encoder(stream, extension); + const pb_field_iter_t *field) { + const pb_extension_t *extension = + *(const pb_extension_t *const *)field->pData; - if (!status) - return false; - - extension = extension->next; - } - - return true; + while (extension) { + bool status; + if (extension->type->encode) + status = extension->type->encode(stream, extension); + else + status = default_extension_encoder(stream, extension); + + if (!status) + return false; + + extension = extension->next; + } + + return true; } /********************* * Encode all fields * *********************/ -static void *pb_const_cast(const void *p) -{ - /* Note: this casts away const, in order to use the common field iterator - * logic for both encoding and decoding. */ - union { - void *p1; - const void *p2; - } t; - t.p2 = p; - return t.p1; -} - -bool checkreturn pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) -{ - pb_field_iter_t iter; - if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) - return true; /* Empty message type */ - - do { - if (PB_LTYPE(iter.pos->type) == PB_LTYPE_EXTENSION) - { - /* Special case for the extension field placeholder */ - if (!encode_extension_field(stream, iter.pos, iter.pData)) - return false; - } - else - { - /* Regular field */ - if (!encode_field(stream, iter.pos, iter.pData)) - return false; - } - } while (pb_field_iter_next(&iter)); - - return true; -} +static void *pb_const_cast(const void *p) { + /* Note: this casts away const, in order to use the common field iterator + * logic for both encoding and decoding. */ + union { + void *p1; + const void *p2; + } t; + t.p2 = p; + return t.p1; +} + +bool checkreturn pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, + const void *src_struct) { + pb_field_iter_t iter; + if (!pb_field_iter_begin(&iter, fields, pb_const_cast(src_struct))) + return true; /* Empty message type */ + + do { + if (PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION) { + /* Special case for the extension field placeholder */ + if (!encode_extension_field(stream, &iter)) + return false; + } else { + /* Regular field */ + if (!encode_field(stream, &iter)) + return false; + } + } while (pb_field_iter_next(&iter)); -bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) -{ - return pb_encode_submessage(stream, fields, src_struct); + return true; } -bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) -{ +bool checkreturn pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, + const void *src_struct, unsigned int flags) { + if ((flags & PB_ENCODE_DELIMITED) != 0) { + return pb_encode_submessage(stream, fields, src_struct); + } else if ((flags & PB_ENCODE_NULLTERMINATED) != 0) { const pb_byte_t zero = 0; if (!pb_encode(stream, fields, src_struct)) - return false; + return false; return pb_write(stream, &zero, 1); + } else { + return pb_encode(stream, fields, src_struct); + } } -bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct) -{ - pb_ostream_t stream = PB_OSTREAM_SIZING; - - if (!pb_encode(&stream, fields, src_struct)) - return false; - - *size = stream.bytes_written; - return true; +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, + const void *src_struct) { + pb_ostream_t stream = PB_OSTREAM_SIZING; + + if (!pb_encode(&stream, fields, src_struct)) + return false; + + *size = stream.bytes_written; + return true; } /******************** * Helper functions * ********************/ -bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) -{ - pb_byte_t buffer[10]; - size_t i = 0; - - if (value <= 0x7F) - { - pb_byte_t v = (pb_byte_t)value; - return pb_write(stream, &v, 1); - } - - while (value) - { - buffer[i] = (pb_byte_t)((value & 0x7F) | 0x80); - value >>= 7; - i++; +/* This function avoids 64-bit shifts as they are quite slow on many platforms. + */ +static bool checkreturn pb_encode_varint_32(pb_ostream_t *stream, uint32_t low, + uint32_t high) { + size_t i = 0; + pb_byte_t buffer[10]; + pb_byte_t byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + + while (i < 4 && (low != 0 || high != 0)) { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(low & 0x7F); + low >>= 7; + } + + if (high) { + byte = (pb_byte_t)(byte | ((high & 0x07) << 4)); + high >>= 3; + + while (high) { + byte |= 0x80; + buffer[i++] = byte; + byte = (pb_byte_t)(high & 0x7F); + high >>= 7; } - buffer[i-1] &= 0x7F; /* Unset top bit on last byte */ - return pb_write(stream, buffer, i); + } + + buffer[i++] = byte; + + return pb_write(stream, buffer, i); } -bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) -{ - pb_uint64_t zigzagged; - if (value < 0) - zigzagged = ~((pb_uint64_t)value << 1); - else - zigzagged = (pb_uint64_t)value << 1; - - return pb_encode_varint(stream, zigzagged); +bool checkreturn pb_encode_varint(pb_ostream_t *stream, pb_uint64_t value) { + if (value <= 0x7F) { + /* Fast path: single byte */ + pb_byte_t byte = (pb_byte_t)value; + return pb_write(stream, &byte, 1); + } else { +#ifdef PB_WITHOUT_64BIT + return pb_encode_varint_32(stream, value, 0); +#else + return pb_encode_varint_32(stream, (uint32_t)value, + (uint32_t)(value >> 32)); +#endif + } +} + +bool checkreturn pb_encode_svarint(pb_ostream_t *stream, pb_int64_t value) { + pb_uint64_t zigzagged; + if (value < 0) + zigzagged = ~((pb_uint64_t)value << 1); + else + zigzagged = (pb_uint64_t)value << 1; + + return pb_encode_varint(stream, zigzagged); } -bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) -{ - uint32_t val = *(const uint32_t*)value; - pb_byte_t bytes[4]; - bytes[0] = (pb_byte_t)(val & 0xFF); - bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); - bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); - bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); - return pb_write(stream, bytes, 4); +bool checkreturn pb_encode_fixed32(pb_ostream_t *stream, const void *value) { + uint32_t val = *(const uint32_t *)value; + pb_byte_t bytes[4]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + return pb_write(stream, bytes, 4); } #ifndef PB_WITHOUT_64BIT -bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) -{ - uint64_t val = *(const uint64_t*)value; - pb_byte_t bytes[8]; - bytes[0] = (pb_byte_t)(val & 0xFF); - bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); - bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); - bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); - bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); - bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); - bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); - bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); - return pb_write(stream, bytes, 8); +bool checkreturn pb_encode_fixed64(pb_ostream_t *stream, const void *value) { + uint64_t val = *(const uint64_t *)value; + pb_byte_t bytes[8]; + bytes[0] = (pb_byte_t)(val & 0xFF); + bytes[1] = (pb_byte_t)((val >> 8) & 0xFF); + bytes[2] = (pb_byte_t)((val >> 16) & 0xFF); + bytes[3] = (pb_byte_t)((val >> 24) & 0xFF); + bytes[4] = (pb_byte_t)((val >> 32) & 0xFF); + bytes[5] = (pb_byte_t)((val >> 40) & 0xFF); + bytes[6] = (pb_byte_t)((val >> 48) & 0xFF); + bytes[7] = (pb_byte_t)((val >> 56) & 0xFF); + return pb_write(stream, bytes, 8); } #endif -bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number) -{ - pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; - return pb_encode_varint(stream, tag); -} - -bool checkreturn pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field) -{ - pb_wire_type_t wiretype; - switch (PB_LTYPE(field->type)) - { - case PB_LTYPE_VARINT: - case PB_LTYPE_UVARINT: - case PB_LTYPE_SVARINT: - wiretype = PB_WT_VARINT; - break; - - case PB_LTYPE_FIXED32: - wiretype = PB_WT_32BIT; - break; - - case PB_LTYPE_FIXED64: - wiretype = PB_WT_64BIT; - break; - - case PB_LTYPE_BYTES: - case PB_LTYPE_STRING: - case PB_LTYPE_SUBMESSAGE: - case PB_LTYPE_FIXED_LENGTH_BYTES: - wiretype = PB_WT_STRING; - break; - - default: - PB_RETURN_ERROR(stream, "invalid field type"); - } - return pb_encode_tag(stream, wiretype, field->tag); +bool checkreturn pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, + uint32_t field_number) { + pb_uint64_t tag = ((pb_uint64_t)field_number << 3) | wiretype; + return pb_encode_varint(stream, tag); } -bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size) -{ - if (!pb_encode_varint(stream, (pb_uint64_t)size)) - return false; - - return pb_write(stream, buffer, size); +bool pb_encode_tag_for_field(pb_ostream_t *stream, + const pb_field_iter_t *field) { + pb_wire_type_t wiretype; + switch (PB_LTYPE(field->type)) { + case PB_LTYPE_BOOL: + case PB_LTYPE_VARINT: + case PB_LTYPE_UVARINT: + case PB_LTYPE_SVARINT: + wiretype = PB_WT_VARINT; + break; + + case PB_LTYPE_FIXED32: + wiretype = PB_WT_32BIT; + break; + + case PB_LTYPE_FIXED64: + wiretype = PB_WT_64BIT; + break; + + case PB_LTYPE_BYTES: + case PB_LTYPE_STRING: + case PB_LTYPE_SUBMESSAGE: + case PB_LTYPE_SUBMSG_W_CB: + case PB_LTYPE_FIXED_LENGTH_BYTES: + wiretype = PB_WT_STRING; + break; + + default: + PB_RETURN_ERROR(stream, "invalid field type"); + } + + return pb_encode_tag(stream, wiretype, field->tag); } -bool checkreturn pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct) -{ - /* First calculate the message size using a non-writing substream. */ - pb_ostream_t substream = PB_OSTREAM_SIZING; - size_t size; - bool status; - - if (!pb_encode(&substream, fields, src_struct)) - { +bool checkreturn pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, + size_t size) { + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + return pb_write(stream, buffer, size); +} + +bool checkreturn pb_encode_submessage(pb_ostream_t *stream, + const pb_msgdesc_t *fields, + const void *src_struct) { + /* First calculate the message size using a non-writing substream. */ + pb_ostream_t substream = PB_OSTREAM_SIZING; + size_t size; + bool status; + + if (!pb_encode(&substream, fields, src_struct)) { #ifndef PB_NO_ERRMSG - stream->errmsg = substream.errmsg; + stream->errmsg = substream.errmsg; #endif - return false; - } - - size = substream.bytes_written; - - if (!pb_encode_varint(stream, (pb_uint64_t)size)) - return false; - - if (stream->callback == NULL) - return pb_write(stream, NULL, size); /* Just sizing */ - - if (stream->bytes_written + size > stream->max_size) - PB_RETURN_ERROR(stream, "stream full"); - - /* Use a substream to verify that a callback doesn't write more than - * what it did the first time. */ - substream.callback = stream->callback; - substream.state = stream->state; - substream.max_size = size; - substream.bytes_written = 0; + return false; + } + + size = substream.bytes_written; + + if (!pb_encode_varint(stream, (pb_uint64_t)size)) + return false; + + if (stream->callback == NULL) + return pb_write(stream, NULL, size); /* Just sizing */ + + if (stream->bytes_written + size > stream->max_size) + PB_RETURN_ERROR(stream, "stream full"); + + /* Use a substream to verify that a callback doesn't write more than + * what it did the first time. */ + substream.callback = stream->callback; + substream.state = stream->state; + substream.max_size = size; + substream.bytes_written = 0; #ifndef PB_NO_ERRMSG - substream.errmsg = NULL; + substream.errmsg = NULL; #endif - - status = pb_encode(&substream, fields, src_struct); - - stream->bytes_written += substream.bytes_written; - stream->state = substream.state; + + status = pb_encode(&substream, fields, src_struct); + + stream->bytes_written += substream.bytes_written; + stream->state = substream.state; #ifndef PB_NO_ERRMSG - stream->errmsg = substream.errmsg; + stream->errmsg = substream.errmsg; #endif - - if (substream.bytes_written != size) - PB_RETURN_ERROR(stream, "submsg size changed"); - - return status; + + if (substream.bytes_written != size) + PB_RETURN_ERROR(stream, "submsg size changed"); + + return status; } /* Field encoders */ -static bool checkreturn pb_enc_varint(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - pb_int64_t value = 0; - - if (field->data_size == sizeof(int_least8_t)) - value = *(const int_least8_t*)src; - else if (field->data_size == sizeof(int_least16_t)) - value = *(const int_least16_t*)src; - else if (field->data_size == sizeof(int32_t)) - value = *(const int32_t*)src; - else if (field->data_size == sizeof(pb_int64_t)) - value = *(const pb_int64_t*)src; - else - PB_RETURN_ERROR(stream, "invalid data_size"); - - return pb_encode_varint(stream, (pb_uint64_t)value); +static bool checkreturn pb_enc_bool(pb_ostream_t *stream, + const pb_field_iter_t *field) { + uint32_t value = safe_read_bool(field->pData) ? 1 : 0; + PB_UNUSED(field); + return pb_encode_varint(stream, value); } -static bool checkreturn pb_enc_uvarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ +static bool checkreturn pb_enc_varint(pb_ostream_t *stream, + const pb_field_iter_t *field) { + if (PB_LTYPE(field->type) == PB_LTYPE_UVARINT) { + /* Perform unsigned integer extension */ pb_uint64_t value = 0; - + if (field->data_size == sizeof(uint_least8_t)) - value = *(const uint_least8_t*)src; + value = *(const uint_least8_t *)field->pData; else if (field->data_size == sizeof(uint_least16_t)) - value = *(const uint_least16_t*)src; + value = *(const uint_least16_t *)field->pData; else if (field->data_size == sizeof(uint32_t)) - value = *(const uint32_t*)src; + value = *(const uint32_t *)field->pData; else if (field->data_size == sizeof(pb_uint64_t)) - value = *(const pb_uint64_t*)src; + value = *(const pb_uint64_t *)field->pData; else - PB_RETURN_ERROR(stream, "invalid data_size"); - - return pb_encode_varint(stream, value); -} + PB_RETURN_ERROR(stream, "invalid data_size"); -static bool checkreturn pb_enc_svarint(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ + return pb_encode_varint(stream, value); + } else { + /* Perform signed integer extension */ pb_int64_t value = 0; - + if (field->data_size == sizeof(int_least8_t)) - value = *(const int_least8_t*)src; + value = *(const int_least8_t *)field->pData; else if (field->data_size == sizeof(int_least16_t)) - value = *(const int_least16_t*)src; + value = *(const int_least16_t *)field->pData; else if (field->data_size == sizeof(int32_t)) - value = *(const int32_t*)src; + value = *(const int32_t *)field->pData; else if (field->data_size == sizeof(pb_int64_t)) - value = *(const pb_int64_t*)src; + value = *(const pb_int64_t *)field->pData; else - PB_RETURN_ERROR(stream, "invalid data_size"); - - return pb_encode_svarint(stream, value); + PB_RETURN_ERROR(stream, "invalid data_size"); + + if (PB_LTYPE(field->type) == PB_LTYPE_SVARINT) + return pb_encode_svarint(stream, value); +#ifdef PB_WITHOUT_64BIT + else if (value < 0) + return pb_encode_varint_32(stream, (uint32_t)value, (uint32_t)-1); +#endif + else + return pb_encode_varint(stream, (pb_uint64_t)value); + } } -static bool checkreturn pb_enc_fixed64(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - PB_UNUSED(field); +static bool checkreturn pb_enc_fixed(pb_ostream_t *stream, + const pb_field_iter_t *field) { +#ifdef PB_CONVERT_DOUBLE_FLOAT + if (field->data_size == sizeof(float) && + PB_LTYPE(field->type) == PB_LTYPE_FIXED64) { + return pb_encode_float_as_double(stream, *(float *)field->pData); + } +#endif + + if (field->data_size == sizeof(uint32_t)) { + return pb_encode_fixed32(stream, field->pData); + } #ifndef PB_WITHOUT_64BIT - return pb_encode_fixed64(stream, src); -#else - PB_UNUSED(src); - PB_RETURN_ERROR(stream, "no 64bit support"); + else if (field->data_size == sizeof(uint64_t)) { + return pb_encode_fixed64(stream, field->pData); + } #endif -} + else { + PB_RETURN_ERROR(stream, "invalid data_size"); + } +} + +static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, + const pb_field_iter_t *field) { + const pb_bytes_array_t *bytes = NULL; + + bytes = (const pb_bytes_array_t *)field->pData; + + if (bytes == NULL) { + /* Treat null pointer as an empty bytes field */ + return pb_encode_string(stream, NULL, 0); + } + + if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && + PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) { + PB_RETURN_ERROR(stream, "bytes size exceeded"); + } + + return pb_encode_string(stream, bytes->bytes, (size_t)bytes->size); +} + +static bool checkreturn pb_enc_string(pb_ostream_t *stream, + const pb_field_iter_t *field) { + size_t size = 0; + size_t max_size = (size_t)field->data_size; + const char *str = (const char *)field->pData; + + if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) { + max_size = (size_t)-1; + } else { + /* pb_dec_string() assumes string fields end with a null + * terminator when the type isn't PB_ATYPE_POINTER, so we + * shouldn't allow more than max-1 bytes to be written to + * allow space for the null terminator. + */ + if (max_size == 0) + PB_RETURN_ERROR(stream, "zero-length string"); + + max_size -= 1; + } + + if (str == NULL) { + size = 0; /* Treat null pointer as an empty string */ + } else { + const char *p = str; + + /* strnlen() is not always available, so just use a loop */ + while (size < max_size && *p != '\0') { + size++; + p++; + } -static bool checkreturn pb_enc_fixed32(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - PB_UNUSED(field); - return pb_encode_fixed32(stream, src); + if (*p != '\0') { + PB_RETURN_ERROR(stream, "unterminated string"); + } + } + +#ifdef PB_VALIDATE_UTF8 + if (!pb_validate_utf8(str)) + PB_RETURN_ERROR(stream, "invalid utf8"); +#endif + + return pb_encode_string(stream, (const pb_byte_t *)str, size); } -static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - const pb_bytes_array_t *bytes = NULL; +static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, + const pb_field_iter_t *field) { + if (field->submsg_desc == NULL) + PB_RETURN_ERROR(stream, "invalid field descriptor"); - bytes = (const pb_bytes_array_t*)src; - - if (src == NULL) - { - /* Treat null pointer as an empty bytes field */ - return pb_encode_string(stream, NULL, 0); - } - - if (PB_ATYPE(field->type) == PB_ATYPE_STATIC && - PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size) - { - PB_RETURN_ERROR(stream, "bytes size exceeded"); - } - - return pb_encode_string(stream, bytes->bytes, bytes->size); -} - -static bool checkreturn pb_enc_string(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - size_t size = 0; - size_t max_size = field->data_size; - const char *p = (const char*)src; - - if (PB_ATYPE(field->type) == PB_ATYPE_POINTER) - max_size = (size_t)-1; - - if (src == NULL) - { - size = 0; /* Treat null pointer as an empty string */ + if (PB_LTYPE(field->type) == PB_LTYPE_SUBMSG_W_CB && field->pSize != NULL) { + /* Message callback is stored right before pSize. */ + pb_callback_t *callback = (pb_callback_t *)field->pSize - 1; + if (callback->funcs.encode) { + if (!callback->funcs.encode(stream, field, &callback->arg)) + return false; } - else - { - /* strnlen() is not always available, so just use a loop */ - while (size < max_size && *p != '\0') - { - size++; - p++; - } + } + + return pb_encode_submessage(stream, field->submsg_desc, field->pData); +} + +static bool checkreturn +pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_iter_t *field) { + return pb_encode_string(stream, (const pb_byte_t *)field->pData, + (size_t)field->data_size); +} + +#ifdef PB_CONVERT_DOUBLE_FLOAT +bool pb_encode_float_as_double(pb_ostream_t *stream, float value) { + union { + float f; + uint32_t i; + } in; + uint8_t sign; + int exponent; + uint64_t mantissa; + + in.f = value; + + /* Decompose input value */ + sign = (uint8_t)((in.i >> 31) & 1); + exponent = (int)((in.i >> 23) & 0xFF) - 127; + mantissa = in.i & 0x7FFFFF; + + if (exponent == 128) { + /* Special value (NaN etc.) */ + exponent = 1024; + } else if (exponent == -127) { + if (!mantissa) { + /* Zero */ + exponent = -1023; + } else { + /* Denormalized */ + mantissa <<= 1; + while (!(mantissa & 0x800000)) { + mantissa <<= 1; + exponent--; + } + mantissa &= 0x7FFFFF; } + } - return pb_encode_string(stream, (const pb_byte_t*)src, size); -} - -static bool checkreturn pb_enc_submessage(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - if (field->ptr == NULL) - PB_RETURN_ERROR(stream, "invalid field descriptor"); - - return pb_encode_submessage(stream, (const pb_field_t*)field->ptr, src); -} + /* Combine fields */ + mantissa <<= 29; + mantissa |= (uint64_t)(exponent + 1023) << 52; + mantissa |= (uint64_t)sign << 63; -static bool checkreturn pb_enc_fixed_length_bytes(pb_ostream_t *stream, const pb_field_t *field, const void *src) -{ - return pb_encode_string(stream, (const pb_byte_t*)src, field->data_size); + return pb_encode_fixed64(stream, &mantissa); } - +#endif diff --git a/src/nanopb/pb_encode.h b/src/nanopb/pb_encode.h index 8bf78dd5..dc222083 100644 --- a/src/nanopb/pb_encode.h +++ b/src/nanopb/pb_encode.h @@ -24,25 +24,24 @@ extern "C" { * 4) Substreams will modify max_size and bytes_written. Don't use them * to calculate any pointers. */ -struct pb_ostream_s -{ +struct pb_ostream_s { #ifdef PB_BUFFER_ONLY - /* Callback pointer is not used in buffer-only configuration. - * Having an int pointer here allows binary compatibility but - * gives an error if someone tries to assign callback function. - * Also, NULL pointer marks a 'sizing stream' that does not - * write anything. - */ - int *callback; + /* Callback pointer is not used in buffer-only configuration. + * Having an int pointer here allows binary compatibility but + * gives an error if someone tries to assign callback function. + * Also, NULL pointer marks a 'sizing stream' that does not + * write anything. + */ + int *callback; #else - bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); + bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); #endif - void *state; /* Free field for use by callback implementation. */ - size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ - size_t bytes_written; /* Number of bytes written so far. */ - + void *state; /* Free field for use by callback implementation. */ + size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */ + size_t bytes_written; /* Number of bytes written so far. */ + #ifndef PB_NO_ERRMSG - const char *errmsg; + const char *errmsg; #endif }; @@ -52,8 +51,8 @@ struct pb_ostream_s /* Encode a single protocol buffers message from C structure into a stream. * Returns true on success, false on any failure. - * The actual struct pointed to by src_struct must match the description in fields. - * All required fields in the struct are assumed to have been filled in. + * The actual struct pointed to by src_struct must match the description in + * fields. All required fields in the struct are assumed to have been filled in. * * Example usage: * MyMessage msg = {}; @@ -64,22 +63,35 @@ struct pb_ostream_s * stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); * pb_encode(&stream, MyMessage_fields, &msg); */ -bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); +bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, + const void *src_struct); -/* Same as pb_encode, but prepends the length of the message as a varint. - * Corresponds to writeDelimitedTo() in Google's protobuf API. +/* Extended version of pb_encode, with several options to control the + * encoding process: + * + * PB_ENCODE_DELIMITED: Prepend the length of message as a varint. + * Corresponds to writeDelimitedTo() in Google's + * protobuf API. + * + * PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination. + * NOTE: This behaviour is not supported in most other + * protobuf implementations, so PB_ENCODE_DELIMITED + * is a better option for compatibility. */ -bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); +#define PB_ENCODE_DELIMITED 0x02U +#define PB_ENCODE_NULLTERMINATED 0x04U +bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, + const void *src_struct, unsigned int flags); -/* Same as pb_encode, but appends a null byte to the message for termination. - * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited() - * is a better option for compatibility. - */ -bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define pb_encode_delimited(s, f, d) pb_encode_ex(s, f, d, PB_ENCODE_DELIMITED) +#define pb_encode_nullterminated(s, f, d) \ + pb_encode_ex(s, f, d, PB_ENCODE_NULLTERMINATED) /* Encode the message to get the size of the encoded data, but do not store * the data. */ -bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct); +bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, + const void *src_struct); /************************************** * Functions for manipulating streams * @@ -96,7 +108,7 @@ pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); /* Pseudo-stream for measuring the size of a message without actually storing * the encoded data. - * + * * Example usage: * MyMessage msg = {}; * pb_ostream_t stream = PB_OSTREAM_SIZING; @@ -104,9 +116,11 @@ pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); * printf("Message size is %d\n", stream.bytes_written); */ #ifndef PB_NO_ERRMSG -#define PB_OSTREAM_SIZING {0,0,0,0,0} +#define PB_OSTREAM_SIZING \ + { 0, 0, 0, 0, 0 } #else -#define PB_OSTREAM_SIZING {0,0,0,0} +#define PB_OSTREAM_SIZING \ + { 0, 0, 0, 0 } #endif /* Function to write into a pb_ostream_t stream. You can use this if you need @@ -114,18 +128,19 @@ pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize); */ bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count); - /************************************************ * Helper functions for writing field callbacks * ************************************************/ /* Encode field header based on type and field number defined in the field * structure. Call this from the callback before writing out field contents. */ -bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field); +bool pb_encode_tag_for_field(pb_ostream_t *stream, + const pb_field_iter_t *field); /* Encode field header by manually specifing wire type. You need to use this * if you want to write out packed arrays from a callback field. */ -bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number); +bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, + uint32_t field_number); /* Encode an integer in the varint format. * This works for bool, enum, int32, int64, uint32 and uint64 field types. */ @@ -144,7 +159,8 @@ bool pb_encode_svarint(pb_ostream_t *stream, int32_t value); #endif /* Encode a string or bytes type field. For strings, pass strlen(s) as size. */ -bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, size_t size); +bool pb_encode_string(pb_ostream_t *stream, const pb_byte_t *buffer, + size_t size); /* Encode a fixed32, sfixed32 or float value. * You need to pass a pointer to a 4-byte wide C variable. */ @@ -156,12 +172,19 @@ bool pb_encode_fixed32(pb_ostream_t *stream, const void *value); bool pb_encode_fixed64(pb_ostream_t *stream, const void *value); #endif +#ifdef PB_CONVERT_DOUBLE_FLOAT +/* Encode a float value so that it appears like a double in the encoded + * message. */ +bool pb_encode_float_as_double(pb_ostream_t *stream, float value); +#endif + /* Encode a submessage field. * You need to pass the pb_field_t array and pointer to struct, just like * with pb_encode(). This internally encodes the submessage twice, first to * calculate message size and then to actually write it out. */ -bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct); +bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, + const void *src_struct); #ifdef __cplusplus } /* extern "C" */ diff --git a/src/nanopb_stubs/amount.pb.c b/src/nanopb_stubs/amount.pb.c index 29524eec..96e1404a 100644 --- a/src/nanopb_stubs/amount.pb.c +++ b/src/nanopb_stubs/amount.pb.c @@ -1,20 +1,9 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #include "amount.pb.h" - -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif - - -const pb_field_t waves_Amount_fields[3] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_Amount, asset_id, asset_id, 0), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_Amount, amount, asset_id, 0), - PB_LAST_FIELD -}; - - -/* @@protoc_insertion_point(eof) */ +PB_BIND(waves_Amount, waves_Amount, AUTO) diff --git a/src/nanopb_stubs/amount.pb.h b/src/nanopb_stubs/amount.pb.h index 09db2cf6..78501070 100644 --- a/src/nanopb_stubs/amount.pb.h +++ b/src/nanopb_stubs/amount.pb.h @@ -1,12 +1,11 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #ifndef PB_WAVES_AMOUNT_PB_H_INCLUDED #define PB_WAVES_AMOUNT_PB_H_INCLUDED #include -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif @@ -16,38 +15,37 @@ extern "C" { /* Struct definitions */ typedef struct _waves_Amount { - pb_callback_t asset_id; - int64_t amount; -/* @@protoc_insertion_point(struct:waves_Amount) */ + pb_callback_t asset_id; + int64_t amount; } waves_Amount; -/* Default values for struct fields */ - /* Initializer values for message structs */ -#define waves_Amount_init_default {{{NULL}, NULL}, 0} -#define waves_Amount_init_zero {{{NULL}, NULL}, 0} +#define waves_Amount_init_default \ + { {{NULL}, NULL}, 0 } +#define waves_Amount_init_zero \ + { {{NULL}, NULL}, 0 } /* Field tags (for use in manual encoding/decoding) */ -#define waves_Amount_asset_id_tag 1 -#define waves_Amount_amount_tag 2 +#define waves_Amount_asset_id_tag 1 +#define waves_Amount_amount_tag 2 /* Struct field encoding specification for nanopb */ -extern const pb_field_t waves_Amount_fields[3]; - -/* Maximum encoded size of messages (where known) */ -/* waves_Amount_size depends on runtime parameters */ +#define waves_Amount_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ + X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_Amount_CALLBACK pb_default_field_callback +#define waves_Amount_DEFAULT NULL -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID +extern const pb_msgdesc_t waves_Amount_msg; -#define AMOUNT_MESSAGES \ +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define waves_Amount_fields &waves_Amount_msg - -#endif +/* Maximum encoded size of messages (where known) */ +/* waves_Amount_size depends on runtime parameters */ #ifdef __cplusplus } /* extern "C" */ #endif -/* @@protoc_insertion_point(eof) */ #endif diff --git a/src/nanopb_stubs/order.pb.c b/src/nanopb_stubs/order.pb.c index 81679cf2..8c48f13d 100644 --- a/src/nanopb_stubs/order.pb.c +++ b/src/nanopb_stubs/order.pb.c @@ -1,61 +1,11 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #include "order.pb.h" - -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif +PB_BIND(waves_AssetPair, waves_AssetPair, AUTO) - -const pb_field_t waves_AssetPair_fields[3] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_AssetPair, amount_asset_id, amount_asset_id, 0), - PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_AssetPair, price_asset_id, amount_asset_id, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_Order_fields[13] = { - PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, waves_Order, chain_id, chain_id, 0), - PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_Order, sender_public_key, chain_id, 0), - PB_FIELD( 3, BYTES , SINGULAR, CALLBACK, OTHER, waves_Order, matcher_public_key, sender_public_key, 0), - PB_FIELD( 4, MESSAGE , SINGULAR, STATIC , OTHER, waves_Order, asset_pair, matcher_public_key, &waves_AssetPair_fields), - PB_FIELD( 5, UENUM , SINGULAR, STATIC , OTHER, waves_Order, order_side, asset_pair, 0), - PB_FIELD( 6, INT64 , SINGULAR, STATIC , OTHER, waves_Order, amount, order_side, 0), - PB_FIELD( 7, INT64 , SINGULAR, STATIC , OTHER, waves_Order, price, amount, 0), - PB_FIELD( 8, INT64 , SINGULAR, STATIC , OTHER, waves_Order, timestamp, price, 0), - PB_FIELD( 9, INT64 , SINGULAR, STATIC , OTHER, waves_Order, expiration, timestamp, 0), - PB_FIELD( 10, MESSAGE , SINGULAR, STATIC , OTHER, waves_Order, matcher_fee, expiration, &waves_Amount_fields), - PB_FIELD( 11, INT32 , SINGULAR, STATIC , OTHER, waves_Order, version, matcher_fee, 0), - PB_FIELD( 12, BYTES , REPEATED, CALLBACK, OTHER, waves_Order, proofs, version, 0), - PB_LAST_FIELD -}; - - - -/* Check that field information fits in pb_field_t */ -#if !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT - * compile-time option. You can do that in pb.h or on compiler command line. - * - * The reason you need to do this is that some of your messages contain tag - * numbers or field sizes that are larger than what can fit in 8 or 16 bit - * field descriptors. - */ -PB_STATIC_ASSERT((pb_membersize(waves_Order, asset_pair) < 65536 && pb_membersize(waves_Order, matcher_fee) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_waves_AssetPair_waves_Order) -#endif - -#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_16BIT - * compile-time option. You can do that in pb.h or on compiler command line. - * - * The reason you need to do this is that some of your messages contain tag - * numbers or field sizes that are larger than what can fit in the default - * 8 bit descriptors. - */ -PB_STATIC_ASSERT((pb_membersize(waves_Order, asset_pair) < 256 && pb_membersize(waves_Order, matcher_fee) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_waves_AssetPair_waves_Order) -#endif - - -/* @@protoc_insertion_point(eof) */ +PB_BIND(waves_Order, waves_Order, AUTO) diff --git a/src/nanopb_stubs/order.pb.h b/src/nanopb_stubs/order.pb.h index 23cd3d4b..d989c3d5 100644 --- a/src/nanopb_stubs/order.pb.h +++ b/src/nanopb_stubs/order.pb.h @@ -1,14 +1,12 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #ifndef PB_WAVES_ORDER_PB_H_INCLUDED #define PB_WAVES_ORDER_PB_H_INCLUDED #include - #include "amount.pb.h" -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif @@ -18,79 +16,110 @@ extern "C" { /* Enum definitions */ typedef enum _waves_Order_Side { - waves_Order_Side_BUY = 0, - waves_Order_Side_SELL = 1 + waves_Order_Side_BUY = 0, + waves_Order_Side_SELL = 1 } waves_Order_Side; -#define _waves_Order_Side_MIN waves_Order_Side_BUY -#define _waves_Order_Side_MAX waves_Order_Side_SELL -#define _waves_Order_Side_ARRAYSIZE ((waves_Order_Side)(waves_Order_Side_SELL+1)) /* Struct definitions */ typedef struct _waves_AssetPair { - pb_callback_t amount_asset_id; - pb_callback_t price_asset_id; -/* @@protoc_insertion_point(struct:waves_AssetPair) */ + pb_callback_t amount_asset_id; + pb_callback_t price_asset_id; } waves_AssetPair; typedef struct _waves_Order { - int32_t chain_id; - pb_callback_t sender_public_key; - pb_callback_t matcher_public_key; - waves_AssetPair asset_pair; - waves_Order_Side order_side; - int64_t amount; - int64_t price; - int64_t timestamp; - int64_t expiration; - waves_Amount matcher_fee; - int32_t version; - pb_callback_t proofs; -/* @@protoc_insertion_point(struct:waves_Order) */ + int32_t chain_id; + pb_callback_t sender_public_key; + pb_callback_t matcher_public_key; + bool has_asset_pair; + waves_AssetPair asset_pair; + waves_Order_Side order_side; + int64_t amount; + int64_t price; + int64_t timestamp; + int64_t expiration; + bool has_matcher_fee; + waves_Amount matcher_fee; + int32_t version; } waves_Order; -/* Default values for struct fields */ +/* Helper constants for enums */ +#define _waves_Order_Side_MIN waves_Order_Side_BUY +#define _waves_Order_Side_MAX waves_Order_Side_SELL +#define _waves_Order_Side_ARRAYSIZE \ + ((waves_Order_Side)(waves_Order_Side_SELL + 1)) /* Initializer values for message structs */ -#define waves_AssetPair_init_default {{{NULL}, NULL}, {{NULL}, NULL}} -#define waves_Order_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}, waves_AssetPair_init_default, _waves_Order_Side_MIN, 0, 0, 0, 0, waves_Amount_init_default, 0, {{NULL}, NULL}} -#define waves_AssetPair_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} -#define waves_Order_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}, waves_AssetPair_init_zero, _waves_Order_Side_MIN, 0, 0, 0, 0, waves_Amount_init_zero, 0, {{NULL}, NULL}} +#define waves_AssetPair_init_default \ + { \ + {{NULL}, NULL}, { {NULL}, NULL } \ + } +#define waves_Order_init_default \ + { \ + 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_default, \ + _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_default, 0 \ + } +#define waves_AssetPair_init_zero \ + { \ + {{NULL}, NULL}, { {NULL}, NULL } \ + } +#define waves_Order_init_zero \ + { \ + 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_zero, \ + _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_zero, 0 \ + } /* Field tags (for use in manual encoding/decoding) */ -#define waves_AssetPair_amount_asset_id_tag 1 -#define waves_AssetPair_price_asset_id_tag 2 -#define waves_Order_chain_id_tag 1 -#define waves_Order_sender_public_key_tag 2 -#define waves_Order_matcher_public_key_tag 3 -#define waves_Order_asset_pair_tag 4 -#define waves_Order_order_side_tag 5 -#define waves_Order_amount_tag 6 -#define waves_Order_price_tag 7 -#define waves_Order_timestamp_tag 8 -#define waves_Order_expiration_tag 9 -#define waves_Order_matcher_fee_tag 10 -#define waves_Order_version_tag 11 -#define waves_Order_proofs_tag 12 +#define waves_AssetPair_amount_asset_id_tag 1 +#define waves_AssetPair_price_asset_id_tag 2 +#define waves_Order_chain_id_tag 1 +#define waves_Order_sender_public_key_tag 2 +#define waves_Order_matcher_public_key_tag 3 +#define waves_Order_asset_pair_tag 4 +#define waves_Order_order_side_tag 5 +#define waves_Order_amount_tag 6 +#define waves_Order_price_tag 7 +#define waves_Order_timestamp_tag 8 +#define waves_Order_expiration_tag 9 +#define waves_Order_matcher_fee_tag 10 +#define waves_Order_version_tag 11 /* Struct field encoding specification for nanopb */ -extern const pb_field_t waves_AssetPair_fields[3]; -extern const pb_field_t waves_Order_fields[13]; +#define waves_AssetPair_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, amount_asset_id, 1) \ + X(a, CALLBACK, SINGULAR, BYTES, price_asset_id, 2) +#define waves_AssetPair_CALLBACK pb_default_field_callback +#define waves_AssetPair_DEFAULT NULL + +#define waves_Order_FIELDLIST(X, a) \ + X(a, STATIC, SINGULAR, INT32, chain_id, 1) \ + X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ + X(a, CALLBACK, SINGULAR, BYTES, matcher_public_key, 3) \ + X(a, STATIC, OPTIONAL, MESSAGE, asset_pair, 4) \ + X(a, STATIC, SINGULAR, UENUM, order_side, 5) \ + X(a, STATIC, SINGULAR, INT64, amount, 6) \ + X(a, STATIC, SINGULAR, INT64, price, 7) \ + X(a, STATIC, SINGULAR, INT64, timestamp, 8) \ + X(a, STATIC, SINGULAR, INT64, expiration, 9) \ + X(a, STATIC, OPTIONAL, MESSAGE, matcher_fee, 10) \ + X(a, STATIC, SINGULAR, INT32, version, 11) +#define waves_Order_CALLBACK pb_default_field_callback +#define waves_Order_DEFAULT NULL +#define waves_Order_asset_pair_MSGTYPE waves_AssetPair +#define waves_Order_matcher_fee_MSGTYPE waves_Amount + +extern const pb_msgdesc_t waves_AssetPair_msg; +extern const pb_msgdesc_t waves_Order_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define waves_AssetPair_fields &waves_AssetPair_msg +#define waves_Order_fields &waves_Order_msg /* Maximum encoded size of messages (where known) */ /* waves_AssetPair_size depends on runtime parameters */ /* waves_Order_size depends on runtime parameters */ -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID - -#define ORDER_MESSAGES \ - - -#endif - #ifdef __cplusplus } /* extern "C" */ #endif -/* @@protoc_insertion_point(eof) */ #endif diff --git a/src/nanopb_stubs/recipient.pb.c b/src/nanopb_stubs/recipient.pb.c index 927abc58..41934730 100644 --- a/src/nanopb_stubs/recipient.pb.c +++ b/src/nanopb_stubs/recipient.pb.c @@ -1,20 +1,9 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #include "recipient.pb.h" - -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif - - -const pb_field_t waves_Recipient_fields[3] = { - PB_ONEOF_FIELD(recipient, 1, BYTES , ONEOF, STATIC , FIRST, waves_Recipient, public_key_hash, public_key_hash, 0), - PB_ONEOF_FIELD(recipient, 2, STRING , ONEOF, STATIC , UNION, waves_Recipient, alias, alias, 0), - PB_LAST_FIELD -}; - - -/* @@protoc_insertion_point(eof) */ +PB_BIND(waves_Recipient, waves_Recipient, AUTO) diff --git a/src/nanopb_stubs/recipient.pb.h b/src/nanopb_stubs/recipient.pb.h index 1e4c3a3d..34b5a54b 100644 --- a/src/nanopb_stubs/recipient.pb.h +++ b/src/nanopb_stubs/recipient.pb.h @@ -1,12 +1,11 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #ifndef PB_WAVES_RECIPIENT_PB_H_INCLUDED #define PB_WAVES_RECIPIENT_PB_H_INCLUDED #include -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif @@ -15,43 +14,53 @@ extern "C" { #endif /* Struct definitions */ -typedef PB_BYTES_ARRAY_T(26) waves_Recipient_public_key_hash_t; typedef struct _waves_Recipient { - pb_size_t which_recipient; - union { - waves_Recipient_public_key_hash_t public_key_hash; - char alias[34]; - } recipient; -/* @@protoc_insertion_point(struct:waves_Recipient) */ + pb_size_t which_recipient; + union { + const char *public_key_hash; + const char *alias; + } recipient; } waves_Recipient; -/* Default values for struct fields */ - /* Initializer values for message structs */ -#define waves_Recipient_init_default {0, {{0, {0}}}} -#define waves_Recipient_init_zero {0, {{0, {0}}}} +#define waves_Recipient_init_default \ + { \ + 0, { \ + { {NULL}, NULL } \ + } \ + } +#define waves_Recipient_init_zero \ + { \ + 0, { \ + { {NULL}, NULL } \ + } \ + } /* Field tags (for use in manual encoding/decoding) */ -#define waves_Recipient_public_key_hash_tag 1 -#define waves_Recipient_alias_tag 2 +#define waves_Recipient_public_key_hash_tag 1 +#define waves_Recipient_alias_tag 2 /* Struct field encoding specification for nanopb */ -extern const pb_field_t waves_Recipient_fields[3]; - -/* Maximum encoded size of messages (where known) */ -#define waves_Recipient_size 36 +#define waves_Recipient_FIELDLIST(X, a) \ + X(a, CALLBACK, ONEOF, BYTES, \ + (recipient, public_key_hash, recipient.public_key_hash), 1) \ + X(a, CALLBACK, ONEOF, STRING, (recipient, alias, recipient.alias), 2) +extern bool waves_Recipient_callback(pb_istream_t *istream, + pb_ostream_t *ostream, + const pb_field_t *field); +#define waves_Recipient_CALLBACK waves_Recipient_callback +#define waves_Recipient_DEFAULT NULL -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID +extern const pb_msgdesc_t waves_Recipient_msg; -#define RECIPIENT_MESSAGES \ +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define waves_Recipient_fields &waves_Recipient_msg - -#endif +/* Maximum encoded size of messages (where known) */ +/* waves_Recipient_size depends on runtime parameters */ #ifdef __cplusplus } /* extern "C" */ #endif -/* @@protoc_insertion_point(eof) */ #endif diff --git a/src/nanopb_stubs/transaction.pb.c b/src/nanopb_stubs/transaction.pb.c index 6f5b4f6d..96322c81 100644 --- a/src/nanopb_stubs/transaction.pb.c +++ b/src/nanopb_stubs/transaction.pb.c @@ -1,193 +1,54 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #include "transaction.pb.h" - -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif +PB_BIND(waves_SignedTransaction, waves_SignedTransaction, AUTO) +PB_BIND(waves_Transaction, waves_Transaction, 2) -const pb_field_t waves_SignedTransaction_fields[3] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_SignedTransaction, transaction, transaction, &waves_Transaction_fields), - PB_FIELD( 2, BYTES , REPEATED, CALLBACK, OTHER, waves_SignedTransaction, proofs, transaction, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_Transaction_fields[23] = { - PB_FIELD( 1, INT32 , SINGULAR, STATIC , FIRST, waves_Transaction, chain_id, chain_id, 0), - PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_Transaction, sender_public_key, chain_id, 0), - PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_Transaction, fee, sender_public_key, &waves_Amount_fields), - PB_FIELD( 4, INT64 , SINGULAR, STATIC , OTHER, waves_Transaction, timestamp, fee, 0), - PB_FIELD( 5, INT32 , SINGULAR, STATIC , OTHER, waves_Transaction, version, timestamp, 0), - PB_ONEOF_FIELD(data, 101, MESSAGE , ONEOF, STATIC , OTHER, waves_Transaction, genesis, version, &waves_GenesisTransactionData_fields), - PB_ONEOF_FIELD(data, 102, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, payment, version, &waves_PaymentTransactionData_fields), - PB_ONEOF_FIELD(data, 103, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, issue, version, &waves_IssueTransactionData_fields), - PB_ONEOF_FIELD(data, 104, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, transfer, version, &waves_TransferTransactionData_fields), - PB_ONEOF_FIELD(data, 105, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, reissue, version, &waves_ReissueTransactionData_fields), - PB_ONEOF_FIELD(data, 106, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, burn, version, &waves_BurnTransactionData_fields), - PB_ONEOF_FIELD(data, 107, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, exchange, version, &waves_ExchangeTransactionData_fields), - PB_ONEOF_FIELD(data, 108, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, lease, version, &waves_LeaseTransactionData_fields), - PB_ONEOF_FIELD(data, 109, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, lease_cancel, version, &waves_LeaseCancelTransactionData_fields), - PB_ONEOF_FIELD(data, 110, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, create_alias, version, &waves_CreateAliasTransactionData_fields), - PB_ONEOF_FIELD(data, 111, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, mass_transfer, version, &waves_MassTransferTransactionData_fields), - PB_ONEOF_FIELD(data, 112, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, data_transaction, version, &waves_DataTransactionData_fields), - PB_ONEOF_FIELD(data, 113, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, set_script, version, &waves_SetScriptTransactionData_fields), - PB_ONEOF_FIELD(data, 114, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, sponsor_fee, version, &waves_SponsorFeeTransactionData_fields), - PB_ONEOF_FIELD(data, 115, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, set_asset_script, version, &waves_SetAssetScriptTransactionData_fields), - PB_ONEOF_FIELD(data, 116, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, invoke_script, version, &waves_InvokeScriptTransactionData_fields), - PB_ONEOF_FIELD(data, 117, MESSAGE , ONEOF, STATIC , UNION, waves_Transaction, update_asset_info, version, &waves_UpdateAssetInfoTransactionData_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_GenesisTransactionData_fields[3] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_GenesisTransactionData, recipient_address, recipient_address, 0), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_GenesisTransactionData, amount, recipient_address, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_PaymentTransactionData_fields[3] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_PaymentTransactionData, recipient_address, recipient_address, 0), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_PaymentTransactionData, amount, recipient_address, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_Attachment_fields[5] = { - PB_ONEOF_FIELD(attachment, 1, INT64 , ONEOF, STATIC , FIRST, waves_Attachment, int_value, int_value, 0), - PB_ONEOF_FIELD(attachment, 2, BOOL , ONEOF, STATIC , UNION, waves_Attachment, bool_value, bool_value, 0), - PB_ONEOF_FIELD(attachment, 3, BYTES , ONEOF, STATIC , UNION, waves_Attachment, binary_value, binary_value, 0), - PB_ONEOF_FIELD(attachment, 4, STRING , ONEOF, STATIC , UNION, waves_Attachment, string_value, string_value, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_TransferTransactionData_fields[4] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_TransferTransactionData, recipient, recipient, &waves_Recipient_fields), - PB_FIELD( 2, MESSAGE , SINGULAR, STATIC , OTHER, waves_TransferTransactionData, amount, recipient, &waves_Amount_fields), - PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_TransferTransactionData, attachment, amount, &waves_Attachment_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_CreateAliasTransactionData_fields[2] = { - PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_CreateAliasTransactionData, alias, alias, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_DataTransactionData_fields[2] = { - PB_FIELD( 1, MESSAGE , REPEATED, CALLBACK, FIRST, waves_DataTransactionData, data, data, &waves_DataTransactionData_DataEntry_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_DataTransactionData_DataEntry_fields[6] = { - PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_DataTransactionData_DataEntry, key, key, 0), - PB_ONEOF_FIELD(value, 10, INT64 , ONEOF, STATIC , OTHER, waves_DataTransactionData_DataEntry, int_value, key, 0), - PB_ONEOF_FIELD(value, 11, BOOL , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, bool_value, key, 0), - PB_ONEOF_FIELD(value, 12, BYTES , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, binary_value, key, 0), - PB_ONEOF_FIELD(value, 13, STRING , ONEOF, STATIC , UNION, waves_DataTransactionData_DataEntry, string_value, key, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_MassTransferTransactionData_fields[4] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_MassTransferTransactionData, asset_id, asset_id, 0), - PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, waves_MassTransferTransactionData, transfers, asset_id, &waves_MassTransferTransactionData_Transfer_fields), - PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, waves_MassTransferTransactionData, attachment, transfers, &waves_Attachment_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_MassTransferTransactionData_Transfer_fields[3] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_MassTransferTransactionData_Transfer, address, address, &waves_Recipient_fields), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_MassTransferTransactionData_Transfer, amount, address, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_LeaseTransactionData_fields[3] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_LeaseTransactionData, recipient, recipient, &waves_Recipient_fields), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_LeaseTransactionData, amount, recipient, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_LeaseCancelTransactionData_fields[2] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_LeaseCancelTransactionData, lease_id, lease_id, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_BurnTransactionData_fields[2] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_BurnTransactionData, asset_amount, asset_amount, &waves_Amount_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_IssueTransactionData_fields[7] = { - PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, waves_IssueTransactionData, name, name, 0), - PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, waves_IssueTransactionData, description, name, 0), - PB_FIELD( 3, INT64 , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, amount, description, 0), - PB_FIELD( 4, INT32 , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, decimals, amount, 0), - PB_FIELD( 5, BOOL , SINGULAR, STATIC , OTHER, waves_IssueTransactionData, reissuable, decimals, 0), - PB_FIELD( 6, BYTES , SINGULAR, CALLBACK, OTHER, waves_IssueTransactionData, script, reissuable, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_ReissueTransactionData_fields[3] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_ReissueTransactionData, asset_amount, asset_amount, &waves_Amount_fields), - PB_FIELD( 2, BOOL , SINGULAR, STATIC , OTHER, waves_ReissueTransactionData, reissuable, asset_amount, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_SetAssetScriptTransactionData_fields[3] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_SetAssetScriptTransactionData, asset_id, asset_id, 0), - PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_SetAssetScriptTransactionData, script, asset_id, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_SetScriptTransactionData_fields[2] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_SetScriptTransactionData, script, script, 0), - PB_LAST_FIELD -}; - -const pb_field_t waves_ExchangeTransactionData_fields[6] = { - PB_FIELD( 1, INT64 , SINGULAR, STATIC , FIRST, waves_ExchangeTransactionData, amount, amount, 0), - PB_FIELD( 2, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, price, amount, 0), - PB_FIELD( 3, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, buy_matcher_fee, price, 0), - PB_FIELD( 4, INT64 , SINGULAR, STATIC , OTHER, waves_ExchangeTransactionData, sell_matcher_fee, buy_matcher_fee, 0), - PB_FIELD( 5, MESSAGE , REPEATED, CALLBACK, OTHER, waves_ExchangeTransactionData, orders, sell_matcher_fee, &waves_Order_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_SponsorFeeTransactionData_fields[2] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_SponsorFeeTransactionData, min_fee, min_fee, &waves_Amount_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_InvokeScriptTransactionData_fields[4] = { - PB_FIELD( 1, MESSAGE , SINGULAR, STATIC , FIRST, waves_InvokeScriptTransactionData, d_app, d_app, &waves_Recipient_fields), - PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, waves_InvokeScriptTransactionData, function_call, d_app, 0), - PB_FIELD( 3, MESSAGE , REPEATED, CALLBACK, OTHER, waves_InvokeScriptTransactionData, payments, function_call, &waves_Amount_fields), - PB_LAST_FIELD -}; - -const pb_field_t waves_UpdateAssetInfoTransactionData_fields[4] = { - PB_FIELD( 1, BYTES , SINGULAR, CALLBACK, FIRST, waves_UpdateAssetInfoTransactionData, asset_id, asset_id, 0), - PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, waves_UpdateAssetInfoTransactionData, name, asset_id, 0), - PB_FIELD( 3, STRING , SINGULAR, CALLBACK, OTHER, waves_UpdateAssetInfoTransactionData, description, name, 0), - PB_LAST_FIELD -}; - - -/* Check that field information fits in pb_field_t */ -#if !defined(PB_FIELD_32BIT) -/* If you get an error here, it means that you need to define PB_FIELD_32BIT - * compile-time option. You can do that in pb.h or on compiler command line. - * - * The reason you need to do this is that some of your messages contain tag - * numbers or field sizes that are larger than what can fit in 8 or 16 bit - * field descriptors. - */ -PB_STATIC_ASSERT((pb_membersize(waves_SignedTransaction, transaction) < 65536 && pb_membersize(waves_Transaction, data.genesis) < 65536 && pb_membersize(waves_Transaction, data.payment) < 65536 && pb_membersize(waves_Transaction, data.issue) < 65536 && pb_membersize(waves_Transaction, data.transfer) < 65536 && pb_membersize(waves_Transaction, data.reissue) < 65536 && pb_membersize(waves_Transaction, data.burn) < 65536 && pb_membersize(waves_Transaction, data.exchange) < 65536 && pb_membersize(waves_Transaction, data.lease) < 65536 && pb_membersize(waves_Transaction, data.lease_cancel) < 65536 && pb_membersize(waves_Transaction, data.create_alias) < 65536 && pb_membersize(waves_Transaction, data.mass_transfer) < 65536 && pb_membersize(waves_Transaction, data.data_transaction) < 65536 && pb_membersize(waves_Transaction, data.set_script) < 65536 && pb_membersize(waves_Transaction, data.sponsor_fee) < 65536 && pb_membersize(waves_Transaction, data.set_asset_script) < 65536 && pb_membersize(waves_Transaction, data.invoke_script) < 65536 && pb_membersize(waves_Transaction, data.update_asset_info) < 65536 && pb_membersize(waves_Transaction, fee) < 65536 && pb_membersize(waves_TransferTransactionData, recipient) < 65536 && pb_membersize(waves_TransferTransactionData, amount) < 65536 && pb_membersize(waves_TransferTransactionData, attachment) < 65536 && pb_membersize(waves_DataTransactionData_DataEntry, value.binary_value) < 65536 && pb_membersize(waves_MassTransferTransactionData, attachment) < 65536 && pb_membersize(waves_MassTransferTransactionData_Transfer, address) < 65536 && pb_membersize(waves_LeaseTransactionData, recipient) < 65536 && pb_membersize(waves_BurnTransactionData, asset_amount) < 65536 && pb_membersize(waves_ReissueTransactionData, asset_amount) < 65536 && pb_membersize(waves_SponsorFeeTransactionData, min_fee) < 65536 && pb_membersize(waves_InvokeScriptTransactionData, d_app) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_waves_SignedTransaction_waves_Transaction_waves_GenesisTransactionData_waves_PaymentTransactionData_waves_Attachment_waves_TransferTransactionData_waves_CreateAliasTransactionData_waves_DataTransactionData_waves_DataTransactionData_DataEntry_waves_MassTransferTransactionData_waves_MassTransferTransactionData_Transfer_waves_LeaseTransactionData_waves_LeaseCancelTransactionData_waves_BurnTransactionData_waves_IssueTransactionData_waves_ReissueTransactionData_waves_SetAssetScriptTransactionData_waves_SetScriptTransactionData_waves_ExchangeTransactionData_waves_SponsorFeeTransactionData_waves_InvokeScriptTransactionData_waves_UpdateAssetInfoTransactionData) -#endif +PB_BIND(waves_GenesisTransactionData, waves_GenesisTransactionData, AUTO) -#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) -#error Field descriptor for waves_DataTransactionData_DataEntry.string_value is too large. Define PB_FIELD_16BIT to fix this. -#endif +PB_BIND(waves_PaymentTransactionData, waves_PaymentTransactionData, AUTO) + +PB_BIND(waves_TransferTransactionData, waves_TransferTransactionData, AUTO) + +PB_BIND(waves_CreateAliasTransactionData, waves_CreateAliasTransactionData, + AUTO) + +PB_BIND(waves_DataTransactionData, waves_DataTransactionData, AUTO) + +PB_BIND(waves_DataTransactionData_DataEntry, + waves_DataTransactionData_DataEntry, AUTO) + +PB_BIND(waves_MassTransferTransactionData, waves_MassTransferTransactionData, + AUTO) + +PB_BIND(waves_LeaseTransactionData, waves_LeaseTransactionData, AUTO) + +PB_BIND(waves_LeaseCancelTransactionData, waves_LeaseCancelTransactionData, + AUTO) + +PB_BIND(waves_BurnTransactionData, waves_BurnTransactionData, AUTO) + +PB_BIND(waves_IssueTransactionData, waves_IssueTransactionData, AUTO) + +PB_BIND(waves_ReissueTransactionData, waves_ReissueTransactionData, AUTO) + +PB_BIND(waves_SetAssetScriptTransactionData, + waves_SetAssetScriptTransactionData, AUTO) + +PB_BIND(waves_SetScriptTransactionData, waves_SetScriptTransactionData, AUTO) + +PB_BIND(waves_ExchangeTransactionData, waves_ExchangeTransactionData, AUTO) + +PB_BIND(waves_SponsorFeeTransactionData, waves_SponsorFeeTransactionData, AUTO) +PB_BIND(waves_InvokeScriptTransactionData, waves_InvokeScriptTransactionData, + AUTO) -/* @@protoc_insertion_point(eof) */ +PB_BIND(waves_UpdateAssetInfoTransactionData, + waves_UpdateAssetInfoTransactionData, AUTO) diff --git a/src/nanopb_stubs/transaction.pb.h b/src/nanopb_stubs/transaction.pb.h index 73c1f44c..9aa8fc62 100644 --- a/src/nanopb_stubs/transaction.pb.h +++ b/src/nanopb_stubs/transaction.pb.h @@ -1,18 +1,14 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.3.9.3 at Wed Apr 15 13:47:10 2020. */ +/* Generated by nanopb-0.4.2-dev */ #ifndef PB_WAVES_TRANSACTION_PB_H_INCLUDED #define PB_WAVES_TRANSACTION_PB_H_INCLUDED #include - #include "amount.pb.h" - #include "recipient.pb.h" - #include "order.pb.h" -/* @@protoc_insertion_point(includes) */ -#if PB_PROTO_HEADER_VERSION != 30 +#if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif @@ -22,361 +18,596 @@ extern "C" { /* Struct definitions */ typedef struct _waves_CreateAliasTransactionData { - pb_callback_t alias; -/* @@protoc_insertion_point(struct:waves_CreateAliasTransactionData) */ + pb_callback_t alias; } waves_CreateAliasTransactionData; typedef struct _waves_DataTransactionData { - pb_callback_t data; -/* @@protoc_insertion_point(struct:waves_DataTransactionData) */ + char dummy_field; } waves_DataTransactionData; +typedef struct _waves_DataTransactionData_DataEntry { + char dummy_field; +} waves_DataTransactionData_DataEntry; + typedef struct _waves_LeaseCancelTransactionData { - pb_callback_t lease_id; -/* @@protoc_insertion_point(struct:waves_LeaseCancelTransactionData) */ + pb_callback_t lease_id; } waves_LeaseCancelTransactionData; +typedef struct _waves_MassTransferTransactionData { + pb_callback_t asset_id; + pb_callback_t attachment; +} waves_MassTransferTransactionData; + typedef struct _waves_SetAssetScriptTransactionData { - pb_callback_t asset_id; - pb_callback_t script; -/* @@protoc_insertion_point(struct:waves_SetAssetScriptTransactionData) */ + pb_callback_t asset_id; } waves_SetAssetScriptTransactionData; typedef struct _waves_SetScriptTransactionData { - pb_callback_t script; -/* @@protoc_insertion_point(struct:waves_SetScriptTransactionData) */ + char dummy_field; } waves_SetScriptTransactionData; typedef struct _waves_UpdateAssetInfoTransactionData { - pb_callback_t asset_id; - pb_callback_t name; - pb_callback_t description; -/* @@protoc_insertion_point(struct:waves_UpdateAssetInfoTransactionData) */ + pb_callback_t asset_id; + pb_callback_t name; + pb_callback_t description; } waves_UpdateAssetInfoTransactionData; -typedef PB_BYTES_ARRAY_T(140) waves_Attachment_binary_value_t; -typedef struct _waves_Attachment { - pb_size_t which_attachment; - union { - int64_t int_value; - bool bool_value; - waves_Attachment_binary_value_t binary_value; - char string_value[140]; - } attachment; -/* @@protoc_insertion_point(struct:waves_Attachment) */ -} waves_Attachment; - typedef struct _waves_BurnTransactionData { - waves_Amount asset_amount; -/* @@protoc_insertion_point(struct:waves_BurnTransactionData) */ + bool has_asset_amount; + waves_Amount asset_amount; } waves_BurnTransactionData; -typedef PB_BYTES_ARRAY_T(32767) waves_DataTransactionData_DataEntry_binary_value_t; -typedef struct _waves_DataTransactionData_DataEntry { - pb_callback_t key; - pb_size_t which_value; - union { - int64_t int_value; - bool bool_value; - waves_DataTransactionData_DataEntry_binary_value_t binary_value; - char string_value[32767]; - } value; -/* @@protoc_insertion_point(struct:waves_DataTransactionData_DataEntry) */ -} waves_DataTransactionData_DataEntry; - typedef struct _waves_ExchangeTransactionData { - int64_t amount; - int64_t price; - int64_t buy_matcher_fee; - int64_t sell_matcher_fee; - pb_callback_t orders; -/* @@protoc_insertion_point(struct:waves_ExchangeTransactionData) */ + int64_t amount; + int64_t price; + int64_t buy_matcher_fee; + int64_t sell_matcher_fee; + pb_callback_t orders; } waves_ExchangeTransactionData; typedef struct _waves_GenesisTransactionData { - pb_callback_t recipient_address; - int64_t amount; -/* @@protoc_insertion_point(struct:waves_GenesisTransactionData) */ + pb_callback_t recipient_address; + int64_t amount; } waves_GenesisTransactionData; typedef struct _waves_InvokeScriptTransactionData { - waves_Recipient d_app; - pb_callback_t function_call; - pb_callback_t payments; -/* @@protoc_insertion_point(struct:waves_InvokeScriptTransactionData) */ + bool has_d_app; + waves_Recipient d_app; + pb_callback_t function_call; + pb_size_t payments_count; + waves_Amount payments[2]; } waves_InvokeScriptTransactionData; typedef struct _waves_IssueTransactionData { - pb_callback_t name; - pb_callback_t description; - int64_t amount; - int32_t decimals; - bool reissuable; - pb_callback_t script; -/* @@protoc_insertion_point(struct:waves_IssueTransactionData) */ + pb_callback_t name; + pb_callback_t description; + int64_t amount; + int32_t decimals; + bool reissuable; } waves_IssueTransactionData; typedef struct _waves_LeaseTransactionData { - waves_Recipient recipient; - int64_t amount; -/* @@protoc_insertion_point(struct:waves_LeaseTransactionData) */ + bool has_recipient; + waves_Recipient recipient; + int64_t amount; } waves_LeaseTransactionData; -typedef struct _waves_MassTransferTransactionData_Transfer { - waves_Recipient address; - int64_t amount; -/* @@protoc_insertion_point(struct:waves_MassTransferTransactionData_Transfer) */ -} waves_MassTransferTransactionData_Transfer; - typedef struct _waves_PaymentTransactionData { - pb_callback_t recipient_address; - int64_t amount; -/* @@protoc_insertion_point(struct:waves_PaymentTransactionData) */ + pb_callback_t recipient_address; + int64_t amount; } waves_PaymentTransactionData; typedef struct _waves_ReissueTransactionData { - waves_Amount asset_amount; - bool reissuable; -/* @@protoc_insertion_point(struct:waves_ReissueTransactionData) */ + bool has_asset_amount; + waves_Amount asset_amount; + bool reissuable; } waves_ReissueTransactionData; typedef struct _waves_SponsorFeeTransactionData { - waves_Amount min_fee; -/* @@protoc_insertion_point(struct:waves_SponsorFeeTransactionData) */ + bool has_min_fee; + waves_Amount min_fee; } waves_SponsorFeeTransactionData; -typedef struct _waves_MassTransferTransactionData { - pb_callback_t asset_id; - pb_callback_t transfers; - waves_Attachment attachment; -/* @@protoc_insertion_point(struct:waves_MassTransferTransactionData) */ -} waves_MassTransferTransactionData; - typedef struct _waves_TransferTransactionData { - waves_Recipient recipient; - waves_Amount amount; - waves_Attachment attachment; -/* @@protoc_insertion_point(struct:waves_TransferTransactionData) */ + bool has_recipient; + waves_Recipient recipient; + bool has_amount; + waves_Amount amount; + pb_callback_t attachment; } waves_TransferTransactionData; typedef struct _waves_Transaction { - int32_t chain_id; - pb_callback_t sender_public_key; - waves_Amount fee; - int64_t timestamp; - int32_t version; - pb_size_t which_data; - union { - waves_GenesisTransactionData genesis; - waves_PaymentTransactionData payment; - waves_IssueTransactionData issue; - waves_TransferTransactionData transfer; - waves_ReissueTransactionData reissue; - waves_BurnTransactionData burn; - waves_ExchangeTransactionData exchange; - waves_LeaseTransactionData lease; - waves_LeaseCancelTransactionData lease_cancel; - waves_CreateAliasTransactionData create_alias; - waves_MassTransferTransactionData mass_transfer; - waves_DataTransactionData data_transaction; - waves_SetScriptTransactionData set_script; - waves_SponsorFeeTransactionData sponsor_fee; - waves_SetAssetScriptTransactionData set_asset_script; - waves_InvokeScriptTransactionData invoke_script; - waves_UpdateAssetInfoTransactionData update_asset_info; - } data; -/* @@protoc_insertion_point(struct:waves_Transaction) */ + int32_t chain_id; + pb_callback_t sender_public_key; + pb_callback_t cb_fee; + bool has_fee; + waves_Amount fee; + int64_t timestamp; + int32_t version; + pb_callback_t cb_data; + pb_size_t which_data; + union { + waves_GenesisTransactionData genesis; + waves_PaymentTransactionData payment; + waves_IssueTransactionData issue; + waves_TransferTransactionData transfer; + waves_ReissueTransactionData reissue; + waves_BurnTransactionData burn; + waves_ExchangeTransactionData exchange; + waves_LeaseTransactionData lease; + waves_LeaseCancelTransactionData lease_cancel; + waves_CreateAliasTransactionData create_alias; + waves_MassTransferTransactionData mass_transfer; + waves_DataTransactionData data_transaction; + waves_SetScriptTransactionData set_script; + waves_SponsorFeeTransactionData sponsor_fee; + waves_SetAssetScriptTransactionData set_asset_script; + waves_InvokeScriptTransactionData invoke_script; + waves_UpdateAssetInfoTransactionData update_asset_info; + } data; } waves_Transaction; typedef struct _waves_SignedTransaction { - waves_Transaction transaction; - pb_callback_t proofs; -/* @@protoc_insertion_point(struct:waves_SignedTransaction) */ + bool has_transaction; + waves_Transaction transaction; + pb_callback_t proofs; } waves_SignedTransaction; -/* Default values for struct fields */ - /* Initializer values for message structs */ -#define waves_SignedTransaction_init_default {waves_Transaction_init_default, {{NULL}, NULL}} -#define waves_Transaction_init_default {0, {{NULL}, NULL}, waves_Amount_init_default, 0, 0, 0, {waves_GenesisTransactionData_init_default}} -#define waves_GenesisTransactionData_init_default {{{NULL}, NULL}, 0} -#define waves_PaymentTransactionData_init_default {{{NULL}, NULL}, 0} -#define waves_Attachment_init_default {0, {0}} -#define waves_TransferTransactionData_init_default {waves_Recipient_init_default, waves_Amount_init_default, waves_Attachment_init_default} -#define waves_CreateAliasTransactionData_init_default {{{NULL}, NULL}} -#define waves_DataTransactionData_init_default {{{NULL}, NULL}} -#define waves_DataTransactionData_DataEntry_init_default {{{NULL}, NULL}, 0, {0}} -#define waves_MassTransferTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, waves_Attachment_init_default} -#define waves_MassTransferTransactionData_Transfer_init_default {waves_Recipient_init_default, 0} -#define waves_LeaseTransactionData_init_default {waves_Recipient_init_default, 0} -#define waves_LeaseCancelTransactionData_init_default {{{NULL}, NULL}} -#define waves_BurnTransactionData_init_default {waves_Amount_init_default} -#define waves_IssueTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} -#define waves_ReissueTransactionData_init_default {waves_Amount_init_default, 0} -#define waves_SetAssetScriptTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}} -#define waves_SetScriptTransactionData_init_default {{{NULL}, NULL}} -#define waves_ExchangeTransactionData_init_default {0, 0, 0, 0, {{NULL}, NULL}} -#define waves_SponsorFeeTransactionData_init_default {waves_Amount_init_default} -#define waves_InvokeScriptTransactionData_init_default {waves_Recipient_init_default, {{NULL}, NULL}, {{NULL}, NULL}} -#define waves_UpdateAssetInfoTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} -#define waves_SignedTransaction_init_zero {waves_Transaction_init_zero, {{NULL}, NULL}} -#define waves_Transaction_init_zero {0, {{NULL}, NULL}, waves_Amount_init_zero, 0, 0, 0, {waves_GenesisTransactionData_init_zero}} -#define waves_GenesisTransactionData_init_zero {{{NULL}, NULL}, 0} -#define waves_PaymentTransactionData_init_zero {{{NULL}, NULL}, 0} -#define waves_Attachment_init_zero {0, {0}} -#define waves_TransferTransactionData_init_zero {waves_Recipient_init_zero, waves_Amount_init_zero, waves_Attachment_init_zero} -#define waves_CreateAliasTransactionData_init_zero {{{NULL}, NULL}} -#define waves_DataTransactionData_init_zero {{{NULL}, NULL}} -#define waves_DataTransactionData_DataEntry_init_zero {{{NULL}, NULL}, 0, {0}} -#define waves_MassTransferTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, waves_Attachment_init_zero} -#define waves_MassTransferTransactionData_Transfer_init_zero {waves_Recipient_init_zero, 0} -#define waves_LeaseTransactionData_init_zero {waves_Recipient_init_zero, 0} -#define waves_LeaseCancelTransactionData_init_zero {{{NULL}, NULL}} -#define waves_BurnTransactionData_init_zero {waves_Amount_init_zero} -#define waves_IssueTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} -#define waves_ReissueTransactionData_init_zero {waves_Amount_init_zero, 0} -#define waves_SetAssetScriptTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} -#define waves_SetScriptTransactionData_init_zero {{{NULL}, NULL}} -#define waves_ExchangeTransactionData_init_zero {0, 0, 0, 0, {{NULL}, NULL}} -#define waves_SponsorFeeTransactionData_init_zero {waves_Amount_init_zero} -#define waves_InvokeScriptTransactionData_init_zero {waves_Recipient_init_zero, {{NULL}, NULL}, {{NULL}, NULL}} -#define waves_UpdateAssetInfoTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} +#define waves_SignedTransaction_init_default \ + { \ + false, waves_Transaction_init_default, { {NULL}, NULL } \ + } +#define waves_Transaction_init_default \ + { \ + 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_default, 0, 0, \ + {{NULL}, NULL}, 0, { \ + waves_GenesisTransactionData_init_default \ + } \ + } +#define waves_GenesisTransactionData_init_default \ + { {{NULL}, NULL}, 0 } +#define waves_PaymentTransactionData_init_default \ + { {{NULL}, NULL}, 0 } +#define waves_TransferTransactionData_init_default \ + { \ + false, waves_Recipient_init_default, false, waves_Amount_init_default, { \ + {NULL}, NULL \ + } \ + } +#define waves_CreateAliasTransactionData_init_default \ + { \ + { {NULL}, NULL } \ + } +#define waves_DataTransactionData_init_default \ + { 0 } +#define waves_DataTransactionData_DataEntry_init_default \ + { 0 } +#define waves_MassTransferTransactionData_init_default \ + { \ + {{NULL}, NULL}, { {NULL}, NULL } \ + } +#define waves_LeaseTransactionData_init_default \ + { false, waves_Recipient_init_default, 0 } +#define waves_LeaseCancelTransactionData_init_default \ + { \ + { {NULL}, NULL } \ + } +#define waves_BurnTransactionData_init_default \ + { false, waves_Amount_init_default } +#define waves_IssueTransactionData_init_default \ + { {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0 } +#define waves_ReissueTransactionData_init_default \ + { false, waves_Amount_init_default, 0 } +#define waves_SetAssetScriptTransactionData_init_default \ + { \ + { {NULL}, NULL } \ + } +#define waves_SetScriptTransactionData_init_default \ + { 0 } +#define waves_ExchangeTransactionData_init_default \ + { \ + 0, 0, 0, 0, { {NULL}, NULL } \ + } +#define waves_SponsorFeeTransactionData_init_default \ + { false, waves_Amount_init_default } +#define waves_InvokeScriptTransactionData_init_default \ + { \ + false, waves_Recipient_init_default, {{NULL}, NULL}, 0, { \ + waves_Amount_init_default, waves_Amount_init_default \ + } \ + } +#define waves_UpdateAssetInfoTransactionData_init_default \ + { \ + {{NULL}, NULL}, {{NULL}, NULL}, { {NULL}, NULL } \ + } +#define waves_SignedTransaction_init_zero \ + { \ + false, waves_Transaction_init_zero, { {NULL}, NULL } \ + } +#define waves_Transaction_init_zero \ + { \ + 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_zero, 0, 0, \ + {{NULL}, NULL}, 0, { \ + waves_GenesisTransactionData_init_zero \ + } \ + } +#define waves_GenesisTransactionData_init_zero \ + { {{NULL}, NULL}, 0 } +#define waves_PaymentTransactionData_init_zero \ + { {{NULL}, NULL}, 0 } +#define waves_TransferTransactionData_init_zero \ + { \ + false, waves_Recipient_init_zero, false, waves_Amount_init_zero, { \ + {NULL}, NULL \ + } \ + } +#define waves_CreateAliasTransactionData_init_zero \ + { \ + { {NULL}, NULL } \ + } +#define waves_DataTransactionData_init_zero \ + { 0 } +#define waves_DataTransactionData_DataEntry_init_zero \ + { 0 } +#define waves_MassTransferTransactionData_init_zero \ + { \ + {{NULL}, NULL}, { {NULL}, NULL } \ + } +#define waves_LeaseTransactionData_init_zero \ + { false, waves_Recipient_init_zero, 0 } +#define waves_LeaseCancelTransactionData_init_zero \ + { \ + { {NULL}, NULL } \ + } +#define waves_BurnTransactionData_init_zero \ + { false, waves_Amount_init_zero } +#define waves_IssueTransactionData_init_zero \ + { {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0 } +#define waves_ReissueTransactionData_init_zero \ + { false, waves_Amount_init_zero, 0 } +#define waves_SetAssetScriptTransactionData_init_zero \ + { \ + { {NULL}, NULL } \ + } +#define waves_SetScriptTransactionData_init_zero \ + { 0 } +#define waves_ExchangeTransactionData_init_zero \ + { \ + 0, 0, 0, 0, { {NULL}, NULL } \ + } +#define waves_SponsorFeeTransactionData_init_zero \ + { false, waves_Amount_init_zero } +#define waves_InvokeScriptTransactionData_init_zero \ + { \ + false, waves_Recipient_init_zero, {{NULL}, NULL}, 0, { \ + waves_Amount_init_zero, waves_Amount_init_zero \ + } \ + } +#define waves_UpdateAssetInfoTransactionData_init_zero \ + { \ + {{NULL}, NULL}, {{NULL}, NULL}, { {NULL}, NULL } \ + } /* Field tags (for use in manual encoding/decoding) */ #define waves_CreateAliasTransactionData_alias_tag 1 -#define waves_DataTransactionData_data_tag 1 #define waves_LeaseCancelTransactionData_lease_id_tag 1 +#define waves_MassTransferTransactionData_asset_id_tag 1 +#define waves_MassTransferTransactionData_attachment_tag 3 #define waves_SetAssetScriptTransactionData_asset_id_tag 1 -#define waves_SetAssetScriptTransactionData_script_tag 2 -#define waves_SetScriptTransactionData_script_tag 1 #define waves_UpdateAssetInfoTransactionData_asset_id_tag 1 #define waves_UpdateAssetInfoTransactionData_name_tag 2 #define waves_UpdateAssetInfoTransactionData_description_tag 3 -#define waves_Attachment_int_value_tag 1 -#define waves_Attachment_bool_value_tag 2 -#define waves_Attachment_binary_value_tag 3 -#define waves_Attachment_string_value_tag 4 #define waves_BurnTransactionData_asset_amount_tag 1 -#define waves_DataTransactionData_DataEntry_int_value_tag 10 -#define waves_DataTransactionData_DataEntry_bool_value_tag 11 -#define waves_DataTransactionData_DataEntry_binary_value_tag 12 -#define waves_DataTransactionData_DataEntry_string_value_tag 13 -#define waves_DataTransactionData_DataEntry_key_tag 1 #define waves_ExchangeTransactionData_amount_tag 1 -#define waves_ExchangeTransactionData_price_tag 2 +#define waves_ExchangeTransactionData_price_tag 2 #define waves_ExchangeTransactionData_buy_matcher_fee_tag 3 #define waves_ExchangeTransactionData_sell_matcher_fee_tag 4 #define waves_ExchangeTransactionData_orders_tag 5 #define waves_GenesisTransactionData_recipient_address_tag 1 -#define waves_GenesisTransactionData_amount_tag 2 +#define waves_GenesisTransactionData_amount_tag 2 #define waves_InvokeScriptTransactionData_d_app_tag 1 #define waves_InvokeScriptTransactionData_function_call_tag 2 #define waves_InvokeScriptTransactionData_payments_tag 3 -#define waves_IssueTransactionData_name_tag 1 +#define waves_IssueTransactionData_name_tag 1 #define waves_IssueTransactionData_description_tag 2 -#define waves_IssueTransactionData_amount_tag 3 -#define waves_IssueTransactionData_decimals_tag 4 +#define waves_IssueTransactionData_amount_tag 3 +#define waves_IssueTransactionData_decimals_tag 4 #define waves_IssueTransactionData_reissuable_tag 5 -#define waves_IssueTransactionData_script_tag 6 #define waves_LeaseTransactionData_recipient_tag 1 -#define waves_LeaseTransactionData_amount_tag 2 -#define waves_MassTransferTransactionData_Transfer_address_tag 1 -#define waves_MassTransferTransactionData_Transfer_amount_tag 2 +#define waves_LeaseTransactionData_amount_tag 2 #define waves_PaymentTransactionData_recipient_address_tag 1 -#define waves_PaymentTransactionData_amount_tag 2 +#define waves_PaymentTransactionData_amount_tag 2 #define waves_ReissueTransactionData_asset_amount_tag 1 #define waves_ReissueTransactionData_reissuable_tag 2 #define waves_SponsorFeeTransactionData_min_fee_tag 1 -#define waves_MassTransferTransactionData_asset_id_tag 1 -#define waves_MassTransferTransactionData_transfers_tag 2 -#define waves_MassTransferTransactionData_attachment_tag 3 #define waves_TransferTransactionData_recipient_tag 1 #define waves_TransferTransactionData_amount_tag 2 #define waves_TransferTransactionData_attachment_tag 3 -#define waves_Transaction_genesis_tag 101 -#define waves_Transaction_payment_tag 102 -#define waves_Transaction_issue_tag 103 -#define waves_Transaction_transfer_tag 104 -#define waves_Transaction_reissue_tag 105 -#define waves_Transaction_burn_tag 106 -#define waves_Transaction_exchange_tag 107 -#define waves_Transaction_lease_tag 108 -#define waves_Transaction_lease_cancel_tag 109 -#define waves_Transaction_create_alias_tag 110 -#define waves_Transaction_mass_transfer_tag 111 -#define waves_Transaction_data_transaction_tag 112 -#define waves_Transaction_set_script_tag 113 -#define waves_Transaction_sponsor_fee_tag 114 -#define waves_Transaction_set_asset_script_tag 115 -#define waves_Transaction_invoke_script_tag 116 -#define waves_Transaction_update_asset_info_tag 117 -#define waves_Transaction_chain_id_tag 1 -#define waves_Transaction_sender_public_key_tag 2 -#define waves_Transaction_fee_tag 3 -#define waves_Transaction_timestamp_tag 4 -#define waves_Transaction_version_tag 5 -#define waves_SignedTransaction_transaction_tag 1 -#define waves_SignedTransaction_proofs_tag 2 +#define waves_Transaction_genesis_tag 101 +#define waves_Transaction_payment_tag 102 +#define waves_Transaction_issue_tag 103 +#define waves_Transaction_transfer_tag 104 +#define waves_Transaction_reissue_tag 105 +#define waves_Transaction_burn_tag 106 +#define waves_Transaction_exchange_tag 107 +#define waves_Transaction_lease_tag 108 +#define waves_Transaction_lease_cancel_tag 109 +#define waves_Transaction_create_alias_tag 110 +#define waves_Transaction_mass_transfer_tag 111 +#define waves_Transaction_data_transaction_tag 112 +#define waves_Transaction_set_script_tag 113 +#define waves_Transaction_sponsor_fee_tag 114 +#define waves_Transaction_set_asset_script_tag 115 +#define waves_Transaction_invoke_script_tag 116 +#define waves_Transaction_update_asset_info_tag 117 +#define waves_Transaction_chain_id_tag 1 +#define waves_Transaction_sender_public_key_tag 2 +#define waves_Transaction_fee_tag 3 +#define waves_Transaction_timestamp_tag 4 +#define waves_Transaction_version_tag 5 +#define waves_SignedTransaction_transaction_tag 1 +#define waves_SignedTransaction_proofs_tag 2 /* Struct field encoding specification for nanopb */ -extern const pb_field_t waves_SignedTransaction_fields[3]; -extern const pb_field_t waves_Transaction_fields[23]; -extern const pb_field_t waves_GenesisTransactionData_fields[3]; -extern const pb_field_t waves_PaymentTransactionData_fields[3]; -extern const pb_field_t waves_Attachment_fields[5]; -extern const pb_field_t waves_TransferTransactionData_fields[4]; -extern const pb_field_t waves_CreateAliasTransactionData_fields[2]; -extern const pb_field_t waves_DataTransactionData_fields[2]; -extern const pb_field_t waves_DataTransactionData_DataEntry_fields[6]; -extern const pb_field_t waves_MassTransferTransactionData_fields[4]; -extern const pb_field_t waves_MassTransferTransactionData_Transfer_fields[3]; -extern const pb_field_t waves_LeaseTransactionData_fields[3]; -extern const pb_field_t waves_LeaseCancelTransactionData_fields[2]; -extern const pb_field_t waves_BurnTransactionData_fields[2]; -extern const pb_field_t waves_IssueTransactionData_fields[7]; -extern const pb_field_t waves_ReissueTransactionData_fields[3]; -extern const pb_field_t waves_SetAssetScriptTransactionData_fields[3]; -extern const pb_field_t waves_SetScriptTransactionData_fields[2]; -extern const pb_field_t waves_ExchangeTransactionData_fields[6]; -extern const pb_field_t waves_SponsorFeeTransactionData_fields[2]; -extern const pb_field_t waves_InvokeScriptTransactionData_fields[4]; -extern const pb_field_t waves_UpdateAssetInfoTransactionData_fields[4]; +#define waves_SignedTransaction_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, transaction, 1) \ + X(a, CALLBACK, REPEATED, BYTES, proofs, 2) +#define waves_SignedTransaction_CALLBACK pb_default_field_callback +#define waves_SignedTransaction_DEFAULT NULL +#define waves_SignedTransaction_transaction_MSGTYPE waves_Transaction + +#define waves_Transaction_FIELDLIST(X, a) \ + X(a, STATIC, SINGULAR, INT32, chain_id, 1) \ + X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ + X(a, STATIC, OPTIONAL, MSG_W_CB, fee, 3) \ + X(a, STATIC, SINGULAR, INT64, timestamp, 4) \ + X(a, STATIC, SINGULAR, INT32, version, 5) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, genesis, data.genesis), 101) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, payment, data.payment), 102) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, issue, data.issue), 103) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, transfer, data.transfer), 104) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, reissue, data.reissue), 105) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, burn, data.burn), 106) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, exchange, data.exchange), 107) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, lease, data.lease), 108) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, lease_cancel, data.lease_cancel), 109) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, create_alias, data.create_alias), 110) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, mass_transfer, data.mass_transfer), \ + 111) \ + X(a, STATIC, ONEOF, MSG_W_CB, \ + (data, data_transaction, data.data_transaction), 112) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, set_script, data.set_script), 113) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, sponsor_fee, data.sponsor_fee), 114) \ + X(a, STATIC, ONEOF, MSG_W_CB, \ + (data, set_asset_script, data.set_asset_script), 115) \ + X(a, STATIC, ONEOF, MSG_W_CB, (data, invoke_script, data.invoke_script), \ + 116) \ + X(a, STATIC, ONEOF, MSG_W_CB, \ + (data, update_asset_info, data.update_asset_info), 117) +#define waves_Transaction_CALLBACK pb_default_field_callback +#define waves_Transaction_DEFAULT NULL +#define waves_Transaction_fee_MSGTYPE waves_Amount +#define waves_Transaction_data_genesis_MSGTYPE waves_GenesisTransactionData +#define waves_Transaction_data_payment_MSGTYPE waves_PaymentTransactionData +#define waves_Transaction_data_issue_MSGTYPE waves_IssueTransactionData +#define waves_Transaction_data_transfer_MSGTYPE waves_TransferTransactionData +#define waves_Transaction_data_reissue_MSGTYPE waves_ReissueTransactionData +#define waves_Transaction_data_burn_MSGTYPE waves_BurnTransactionData +#define waves_Transaction_data_exchange_MSGTYPE waves_ExchangeTransactionData +#define waves_Transaction_data_lease_MSGTYPE waves_LeaseTransactionData +#define waves_Transaction_data_lease_cancel_MSGTYPE \ + waves_LeaseCancelTransactionData +#define waves_Transaction_data_create_alias_MSGTYPE \ + waves_CreateAliasTransactionData +#define waves_Transaction_data_mass_transfer_MSGTYPE \ + waves_MassTransferTransactionData +#define waves_Transaction_data_data_transaction_MSGTYPE \ + waves_DataTransactionData +#define waves_Transaction_data_set_script_MSGTYPE waves_SetScriptTransactionData +#define waves_Transaction_data_sponsor_fee_MSGTYPE \ + waves_SponsorFeeTransactionData +#define waves_Transaction_data_set_asset_script_MSGTYPE \ + waves_SetAssetScriptTransactionData +#define waves_Transaction_data_invoke_script_MSGTYPE \ + waves_InvokeScriptTransactionData +#define waves_Transaction_data_update_asset_info_MSGTYPE \ + waves_UpdateAssetInfoTransactionData + +#define waves_GenesisTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, recipient_address, 1) \ + X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_GenesisTransactionData_CALLBACK pb_default_field_callback +#define waves_GenesisTransactionData_DEFAULT NULL + +#define waves_PaymentTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, recipient_address, 1) \ + X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_PaymentTransactionData_CALLBACK pb_default_field_callback +#define waves_PaymentTransactionData_DEFAULT NULL + +#define waves_TransferTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ + X(a, STATIC, OPTIONAL, MESSAGE, amount, 2) \ + X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) +#define waves_TransferTransactionData_CALLBACK pb_default_field_callback +#define waves_TransferTransactionData_DEFAULT NULL +#define waves_TransferTransactionData_recipient_MSGTYPE waves_Recipient +#define waves_TransferTransactionData_amount_MSGTYPE waves_Amount + +#define waves_CreateAliasTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, STRING, alias, 1) +#define waves_CreateAliasTransactionData_CALLBACK pb_default_field_callback +#define waves_CreateAliasTransactionData_DEFAULT NULL + +#define waves_DataTransactionData_FIELDLIST(X, a) + +#define waves_DataTransactionData_CALLBACK NULL +#define waves_DataTransactionData_DEFAULT NULL + +#define waves_DataTransactionData_DataEntry_FIELDLIST(X, a) + +#define waves_DataTransactionData_DataEntry_CALLBACK NULL +#define waves_DataTransactionData_DataEntry_DEFAULT NULL + +#define waves_MassTransferTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ + X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) +#define waves_MassTransferTransactionData_CALLBACK pb_default_field_callback +#define waves_MassTransferTransactionData_DEFAULT NULL + +#define waves_LeaseTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ + X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_LeaseTransactionData_CALLBACK NULL +#define waves_LeaseTransactionData_DEFAULT NULL +#define waves_LeaseTransactionData_recipient_MSGTYPE waves_Recipient + +#define waves_LeaseCancelTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, lease_id, 1) +#define waves_LeaseCancelTransactionData_CALLBACK pb_default_field_callback +#define waves_LeaseCancelTransactionData_DEFAULT NULL + +#define waves_BurnTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) +#define waves_BurnTransactionData_CALLBACK NULL +#define waves_BurnTransactionData_DEFAULT NULL +#define waves_BurnTransactionData_asset_amount_MSGTYPE waves_Amount + +#define waves_IssueTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, STRING, name, 1) \ + X(a, CALLBACK, SINGULAR, STRING, description, 2) \ + X(a, STATIC, SINGULAR, INT64, amount, 3) \ + X(a, STATIC, SINGULAR, INT32, decimals, 4) \ + X(a, STATIC, SINGULAR, BOOL, reissuable, 5) +#define waves_IssueTransactionData_CALLBACK pb_default_field_callback +#define waves_IssueTransactionData_DEFAULT NULL + +#define waves_ReissueTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) \ + X(a, STATIC, SINGULAR, BOOL, reissuable, 2) +#define waves_ReissueTransactionData_CALLBACK NULL +#define waves_ReissueTransactionData_DEFAULT NULL +#define waves_ReissueTransactionData_asset_amount_MSGTYPE waves_Amount + +#define waves_SetAssetScriptTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) +#define waves_SetAssetScriptTransactionData_CALLBACK pb_default_field_callback +#define waves_SetAssetScriptTransactionData_DEFAULT NULL + +#define waves_SetScriptTransactionData_FIELDLIST(X, a) + +#define waves_SetScriptTransactionData_CALLBACK NULL +#define waves_SetScriptTransactionData_DEFAULT NULL + +#define waves_ExchangeTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, SINGULAR, INT64, amount, 1) \ + X(a, STATIC, SINGULAR, INT64, price, 2) \ + X(a, STATIC, SINGULAR, INT64, buy_matcher_fee, 3) \ + X(a, STATIC, SINGULAR, INT64, sell_matcher_fee, 4) \ + X(a, CALLBACK, REPEATED, MESSAGE, orders, 5) +#define waves_ExchangeTransactionData_CALLBACK pb_default_field_callback +#define waves_ExchangeTransactionData_DEFAULT NULL +#define waves_ExchangeTransactionData_orders_MSGTYPE waves_Order + +#define waves_SponsorFeeTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, min_fee, 1) +#define waves_SponsorFeeTransactionData_CALLBACK NULL +#define waves_SponsorFeeTransactionData_DEFAULT NULL +#define waves_SponsorFeeTransactionData_min_fee_MSGTYPE waves_Amount + +#define waves_InvokeScriptTransactionData_FIELDLIST(X, a) \ + X(a, STATIC, OPTIONAL, MESSAGE, d_app, 1) \ + X(a, CALLBACK, SINGULAR, BYTES, function_call, 2) \ + X(a, STATIC, REPEATED, MESSAGE, payments, 3) +#define waves_InvokeScriptTransactionData_CALLBACK pb_default_field_callback +#define waves_InvokeScriptTransactionData_DEFAULT NULL +#define waves_InvokeScriptTransactionData_d_app_MSGTYPE waves_Recipient +#define waves_InvokeScriptTransactionData_payments_MSGTYPE waves_Amount + +#define waves_UpdateAssetInfoTransactionData_FIELDLIST(X, a) \ + X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ + X(a, CALLBACK, SINGULAR, STRING, name, 2) \ + X(a, CALLBACK, SINGULAR, STRING, description, 3) +#define waves_UpdateAssetInfoTransactionData_CALLBACK pb_default_field_callback +#define waves_UpdateAssetInfoTransactionData_DEFAULT NULL + +extern const pb_msgdesc_t waves_SignedTransaction_msg; +extern const pb_msgdesc_t waves_Transaction_msg; +extern const pb_msgdesc_t waves_GenesisTransactionData_msg; +extern const pb_msgdesc_t waves_PaymentTransactionData_msg; +extern const pb_msgdesc_t waves_TransferTransactionData_msg; +extern const pb_msgdesc_t waves_CreateAliasTransactionData_msg; +extern const pb_msgdesc_t waves_DataTransactionData_msg; +extern const pb_msgdesc_t waves_DataTransactionData_DataEntry_msg; +extern const pb_msgdesc_t waves_MassTransferTransactionData_msg; +extern const pb_msgdesc_t waves_LeaseTransactionData_msg; +extern const pb_msgdesc_t waves_LeaseCancelTransactionData_msg; +extern const pb_msgdesc_t waves_BurnTransactionData_msg; +extern const pb_msgdesc_t waves_IssueTransactionData_msg; +extern const pb_msgdesc_t waves_ReissueTransactionData_msg; +extern const pb_msgdesc_t waves_SetAssetScriptTransactionData_msg; +extern const pb_msgdesc_t waves_SetScriptTransactionData_msg; +extern const pb_msgdesc_t waves_ExchangeTransactionData_msg; +extern const pb_msgdesc_t waves_SponsorFeeTransactionData_msg; +extern const pb_msgdesc_t waves_InvokeScriptTransactionData_msg; +extern const pb_msgdesc_t waves_UpdateAssetInfoTransactionData_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define waves_SignedTransaction_fields &waves_SignedTransaction_msg +#define waves_Transaction_fields &waves_Transaction_msg +#define waves_GenesisTransactionData_fields &waves_GenesisTransactionData_msg +#define waves_PaymentTransactionData_fields &waves_PaymentTransactionData_msg +#define waves_TransferTransactionData_fields &waves_TransferTransactionData_msg +#define waves_CreateAliasTransactionData_fields \ + &waves_CreateAliasTransactionData_msg +#define waves_DataTransactionData_fields &waves_DataTransactionData_msg +#define waves_DataTransactionData_DataEntry_fields \ + &waves_DataTransactionData_DataEntry_msg +#define waves_MassTransferTransactionData_fields \ + &waves_MassTransferTransactionData_msg +#define waves_LeaseTransactionData_fields &waves_LeaseTransactionData_msg +#define waves_LeaseCancelTransactionData_fields \ + &waves_LeaseCancelTransactionData_msg +#define waves_BurnTransactionData_fields &waves_BurnTransactionData_msg +#define waves_IssueTransactionData_fields &waves_IssueTransactionData_msg +#define waves_ReissueTransactionData_fields &waves_ReissueTransactionData_msg +#define waves_SetAssetScriptTransactionData_fields \ + &waves_SetAssetScriptTransactionData_msg +#define waves_SetScriptTransactionData_fields \ + &waves_SetScriptTransactionData_msg +#define waves_ExchangeTransactionData_fields &waves_ExchangeTransactionData_msg +#define waves_SponsorFeeTransactionData_fields \ + &waves_SponsorFeeTransactionData_msg +#define waves_InvokeScriptTransactionData_fields \ + &waves_InvokeScriptTransactionData_msg +#define waves_UpdateAssetInfoTransactionData_fields \ + &waves_UpdateAssetInfoTransactionData_msg /* Maximum encoded size of messages (where known) */ /* waves_SignedTransaction_size depends on runtime parameters */ /* waves_Transaction_size depends on runtime parameters */ /* waves_GenesisTransactionData_size depends on runtime parameters */ /* waves_PaymentTransactionData_size depends on runtime parameters */ -#define waves_Attachment_size 143 -#define waves_TransferTransactionData_size (190 + waves_Amount_size) +/* waves_TransferTransactionData_size depends on runtime parameters */ /* waves_CreateAliasTransactionData_size depends on runtime parameters */ -/* waves_DataTransactionData_size depends on runtime parameters */ -/* waves_DataTransactionData_DataEntry_size depends on runtime parameters */ +#define waves_DataTransactionData_size 0 +#define waves_DataTransactionData_DataEntry_size 0 /* waves_MassTransferTransactionData_size depends on runtime parameters */ -#define waves_MassTransferTransactionData_Transfer_size 49 -#define waves_LeaseTransactionData_size 49 +#define waves_LeaseTransactionData_size (17 + waves_Recipient_size) /* waves_LeaseCancelTransactionData_size depends on runtime parameters */ -#define waves_BurnTransactionData_size (6 + waves_Amount_size) +#define waves_BurnTransactionData_size (6 + waves_Amount_size) /* waves_IssueTransactionData_size depends on runtime parameters */ -#define waves_ReissueTransactionData_size (8 + waves_Amount_size) +#define waves_ReissueTransactionData_size (8 + waves_Amount_size) /* waves_SetAssetScriptTransactionData_size depends on runtime parameters */ -/* waves_SetScriptTransactionData_size depends on runtime parameters */ +#define waves_SetScriptTransactionData_size 0 /* waves_ExchangeTransactionData_size depends on runtime parameters */ -#define waves_SponsorFeeTransactionData_size (6 + waves_Amount_size) +#define waves_SponsorFeeTransactionData_size (6 + waves_Amount_size) /* waves_InvokeScriptTransactionData_size depends on runtime parameters */ /* waves_UpdateAssetInfoTransactionData_size depends on runtime parameters */ -/* Message IDs (where set with "msgid" option) */ -#ifdef PB_MSGID - -#define TRANSACTION_MESSAGES \ - - -#endif - #ifdef __cplusplus } /* extern "C" */ #endif -/* @@protoc_insertion_point(eof) */ #endif diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index d55a61fe..c189a66e 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -25,6 +25,7 @@ #include "cx.h" #include "../ui_logic.h" +////////////////////////////////////////////////////////////////////////////// const bagl_element_t ui_idle_blue[] = { // type userid x y w h str rad // fill fg bg fid iid txt touchparams... ] @@ -114,10 +115,3259 @@ const bagl_element_t ui_idle_blue[] = { NULL, NULL}, }; +////////////////////////////////////////////////////////////////////////////// +const bagl_element_t ui_verify_transfer_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "transfer", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x70, 30, 140, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x10, 130, 140, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 153, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 166, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 166, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 179, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 192, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Destination", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 192, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 205, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 270, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Attachment", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 270, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line4, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 283, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_data_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Data Transaction", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_issue_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Asset issue", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Name", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Description", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Decimals", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line4, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Reissuable", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line5, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_reissue_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Asset reissue", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Reissuable", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_burn_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Asset burn", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_lease_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Asset leasing", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "To", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_cancel_lease_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Asset leasing cancel", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Lease id", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_create_alias_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Creating alias", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Alias", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_masstransfer_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Mass Transfer", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 166, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 166, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 179, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 270, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Attachment", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 270, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 283, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_set_ac_script_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Set account script", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_sponsorship_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Fee sponsoring", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_set_as_script_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Set asset script", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, -const bagl_element_t ui_verify_transfer_blue[] = { - {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, - 0x000000, 0, 0}, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, NULL, 0, 0, @@ -126,10 +3376,20 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - // erase screen (only under the status bar) - {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, - COLOR_APP, 0, 0}, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, 0, 0, 0, @@ -137,10 +3397,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - /// TOP STATUS BAR - {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, - BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, - "CONFIRM SIGNATURE", + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, 0, 0, 0, @@ -148,9 +3407,20 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - // BADGE_TRANSACTION.GIF - {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, - &C_badge_transaction, + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, 0, 0, 0, @@ -158,18 +3428,30 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, - COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, - "Confirm", + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, 0, 0, 0, NULL, NULL, NULL}, - {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, - COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, - "transfer", + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, 0, 0, 0, @@ -177,9 +3459,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, - COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, - "Check and confirm data", + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, 0, 0, 0, @@ -187,9 +3469,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x70, 30, 140, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - "Amount", + "Transaction ID", 0, 0, 0, @@ -197,10 +3479,10 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, // x-18 when ... - {{BAGL_LABEL, 0x10, 130, 140, 160, 30, 0, 0, BAGL_FILL, 0x000000, + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line1, + (const char *)tmp_ctx.signing_context.ui.txid, 0, 0, 0, @@ -208,7 +3490,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_RECTANGLE, 0x31, 30, 153, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, 0, @@ -218,7 +3500,108 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 166, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_issue_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Update asset info", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, "Asset", 0, @@ -228,10 +3611,10 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, // x-18 when ... - {{BAGL_LABEL, 0x11, 130, 166, 160, 30, 0, 0, BAGL_FILL, 0x000000, + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line2, + (const char *)tmp_ctx.signing_context.ui.line1, 0, 0, 0, @@ -239,7 +3622,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_RECTANGLE, 0x31, 30, 179, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, 0, @@ -249,9 +3632,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 192, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - "Destination", + "Name", 0, 0, 0, @@ -259,10 +3642,10 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, // x-18 when ... - {{BAGL_LABEL, 0x11, 130, 192, 160, 30, 0, 0, BAGL_FILL, 0x000000, + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line3, + (const char *)tmp_ctx.signing_context.ui.line2, 0, 0, 0, @@ -270,7 +3653,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_RECTANGLE, 0x31, 30, 205, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, 0, @@ -282,7 +3665,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - "Fee", + "Description", 0, 0, 0, @@ -293,7 +3676,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line4, + (const char *)tmp_ctx.signing_context.ui.line3, 0, 0, 0, @@ -311,9 +3694,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - "Fee asset", + "Fee", 0, 0, 0, @@ -321,10 +3704,10 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, // x-18 when ... - {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line5, + (const char *)tmp_ctx.signing_context.ui.fee_amount, 0, 0, 0, @@ -332,7 +3715,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, 0, @@ -342,9 +3725,9 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 270, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - "Attachment", + "Fee asset", 0, 0, 0, @@ -352,10 +3735,10 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, // x-18 when ... - {{BAGL_LABEL, 0x11, 130, 270, 160, 30, 0, 0, BAGL_FILL, 0x000000, + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line6, + (const char *)tmp_ctx.signing_context.ui.fee_asset, 0, 0, 0, @@ -363,7 +3746,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { NULL, NULL}, - {{BAGL_RECTANGLE, 0x31, 30, 283, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, 0, @@ -386,7 +3769,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line7, + (const char *)tmp_ctx.signing_context.ui.from, 0, 0, 0, @@ -417,7 +3800,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line8, + (const char *)tmp_ctx.signing_context.ui.txid, 0, 0, 0, @@ -516,7 +3899,7 @@ const bagl_element_t ui_approval_blue[] = { NULL}, {{BAGL_LABELINE, 0x50, 154, 117, 320, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, - (const char *)ui_context.line1, + (const char *)tmp_ctx.signing_context.ui.line1, 0, 0, 0, @@ -536,7 +3919,7 @@ const bagl_element_t ui_approval_blue[] = { {{BAGL_LABELINE, 0x70, 30, 196, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, - (const char *)ui_context.line2, + (const char *)tmp_ctx.signing_context.ui.line2, 0, 0, 0, @@ -547,7 +3930,7 @@ const bagl_element_t ui_approval_blue[] = { {{BAGL_LABELINE, 0x10, 130, 200, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line3, + (const char *)tmp_ctx.signing_context.ui.line3, 0, 0, 0, @@ -578,7 +3961,7 @@ const bagl_element_t ui_approval_blue[] = { {{BAGL_LABELINE, 0x11, 130, 245, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)ui_context.line4, + (const char *)tmp_ctx.signing_context.ui.from, 0, 0, 0, @@ -746,10 +4129,73 @@ unsigned int ui_address_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; } -unsigned int ui_verify_transfer_blue_button(unsigned int button_mask, - unsigned int button_mask_counter) { +unsigned int ui_verify_data_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int ui_verify_issue_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int ui_verify_reissue_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int ui_verify_burn_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int ui_verify_lease_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_cancel_lease_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_create_alias_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_masstransfer_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_set_ac_script_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_sponsorship_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_set_as_script_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + +unsigned int +ui_verify_update_asset_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { return 0; } + unsigned int ui_approval_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index 931554b5..dc543e2d 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -90,50 +90,51 @@ void display_if_buffer_not_empty(const char *buffer, size_t buffer_len) { UX_STEP_NOCB(ux_transfer_1_step, pnn, { &C_icon_eye, - "Review", - "transfer", + "Confirm", + "Transfer", }); UX_STEP_NOCB(ux_transfer_2_step, bnnn_paging, { .title = "Amount", - .text = (const char *)ui_context.line1, + .text = (const char *)tmp_ctx.signing_context.ui.line1, }); UX_STEP_NOCB(ux_transfer_3_step, bnnn_paging, { .title = "Asset", - .text = (const char *)ui_context.line2, + .text = (const char *)tmp_ctx.signing_context.ui.line2, }); UX_STEP_NOCB(ux_transfer_4_step, bnnn_paging, { .title = "To", - .text = (const char *)ui_context.line3, + .text = (const char *)tmp_ctx.signing_context.ui.line3, }); UX_STEP_NOCB(ux_transfer_5_step, bnnn_paging, { .title = "Fee", - .text = (const char *)ui_context.line4, + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, }); UX_STEP_NOCB(ux_transfer_6_step, bnnn_paging, { .title = "Fee asset", - .text = (const char *)ui_context.line5, - }); -UX_STEP_NOCB_INIT(ux_transfer_7_step, bnnn_paging, - display_if_buffer_not_empty((const char *)ui_context.line6, - sizeof(ui_context.line6)), - { - .title = "Attachment", - .text = (const char *)ui_context.line6, - }); + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB_INIT( + ux_transfer_7_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, + sizeof(tmp_ctx.signing_context.ui.line4)), + { + .title = "Attachment", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); UX_STEP_NOCB(ux_transfer_8_step, bnnn_paging, { .title = "From", - .text = (const char *)ui_context.line7, + .text = (const char *)tmp_ctx.signing_context.ui.from, }); UX_STEP_NOCB(ux_transfer_9_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)ui_context.line8, + .text = (const char *)tmp_ctx.signing_context.ui.txid, }); UX_STEP_VALID(ux_transfer_10_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -154,17 +155,764 @@ UX_FLOW(ux_transfer_flow, &ux_transfer_1_step, &ux_transfer_2_step, ////////////////////////////////////////////////////////////////////// +UX_STEP_NOCB(ux_data_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Data transaction", + }); +UX_STEP_NOCB(ux_data_2_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_data_3_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_data_4_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_data_5_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_data_6_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_data_7_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_data_flow, &ux_data_1_step, &ux_data_2_step, &ux_data_3_step, + &ux_data_4_step, &ux_data_5_step, &ux_data_6_step, &ux_data_7_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_issue_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Asset issue", + }); +UX_STEP_NOCB(ux_issue_2_step, bnnn_paging, + { + .title = "Name", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_issue_3_step, bnnn_paging, + { + .title = "Description", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_issue_4_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB(ux_issue_5_step, bnnn_paging, + { + .title = "Decimals", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); +UX_STEP_NOCB(ux_issue_6_step, bnnn_paging, + { + .title = "Reissuable", + .text = (const char *)tmp_ctx.signing_context.ui.line5, + }); +UX_STEP_NOCB(ux_issue_7_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_issue_8_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_issue_9_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_issue_10_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_issue_11_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_issue_12_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_issue_flow, &ux_issue_1_step, &ux_issue_2_step, &ux_issue_3_step, + &ux_issue_4_step, &ux_issue_5_step, &ux_issue_6_step, &ux_issue_7_step, + &ux_issue_8_step, &ux_issue_9_step, &ux_issue_10_step, + &ux_issue_11_step, &ux_issue_12_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_reissue_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Asset reissue", + }); +UX_STEP_NOCB(ux_reissue_2_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_reissue_3_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_reissue_4_step, bnnn_paging, + { + .title = "Reissuable", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB(ux_reissue_5_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_reissue_6_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_reissue_7_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_reissue_8_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_reissue_9_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_reissue_10_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_reissue_flow, &ux_reissue_1_step, &ux_reissue_2_step, + &ux_reissue_3_step, &ux_reissue_4_step, &ux_reissue_5_step, + &ux_reissue_6_step, &ux_reissue_7_step, &ux_reissue_8_step, + &ux_reissue_9_step, &ux_reissue_10_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_burn_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Asset burn", + }); +UX_STEP_NOCB(ux_burn_2_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_burn_3_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_burn_4_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_burn_5_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_burn_6_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_burn_7_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_burn_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_burn_9_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_burn_flow, &ux_burn_1_step, &ux_burn_2_step, &ux_burn_3_step, + &ux_burn_4_step, &ux_burn_5_step, &ux_burn_6_step, &ux_burn_7_step, + &ux_burn_8_step, &ux_burn_9_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_lease_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Asset leasing", + }); +UX_STEP_NOCB(ux_lease_2_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_lease_3_step, bnnn_paging, + { + .title = "To", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB(ux_lease_4_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_lease_5_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_lease_6_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_lease_7_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_lease_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_lease_9_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_lease_flow, &ux_lease_1_step, &ux_lease_2_step, &ux_lease_3_step, + &ux_lease_4_step, &ux_lease_5_step, &ux_lease_6_step, &ux_lease_7_step, + &ux_lease_8_step, &ux_lease_9_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_cancel_lease_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Asset leasing cancel", + }); +UX_STEP_NOCB(ux_cancel_lease_2_step, bnnn_paging, + { + .title = "Lease id", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_cancel_lease_3_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_cancel_lease_4_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_cancel_lease_5_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_cancel_lease_6_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_cancel_lease_7_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_cancel_lease_8_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_cancel_lease_flow, &ux_cancel_lease_1_step, &ux_cancel_lease_2_step, + &ux_cancel_lease_3_step, &ux_cancel_lease_4_step, + &ux_cancel_lease_5_step, &ux_cancel_lease_6_step, + &ux_cancel_lease_7_step, &ux_cancel_lease_8_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_create_alias_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Creating alias", + }); +UX_STEP_NOCB(ux_create_alias_2_step, bnnn_paging, + { + .title = "Alias", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_create_alias_3_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_create_alias_4_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_create_alias_5_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_create_alias_6_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_create_alias_7_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_create_alias_8_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_create_alias_flow, &ux_create_alias_1_step, &ux_create_alias_2_step, + &ux_create_alias_3_step, &ux_create_alias_4_step, + &ux_create_alias_5_step, &ux_create_alias_6_step, + &ux_create_alias_7_step, &ux_create_alias_8_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_masstransfer_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Mass transfer", + }); +UX_STEP_NOCB(ux_masstransfer_2_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_masstransfer_3_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_masstransfer_4_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB_INIT( + ux_masstransfer_5_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line2, + sizeof(tmp_ctx.signing_context.ui.line2)), + { + .title = "Attachment", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_masstransfer_6_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); +UX_STEP_NOCB(ux_masstransfer_7_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_masstransfer_8_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_masstransfer_9_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_masstransfer_flow, &ux_masstransfer_1_step, &ux_masstransfer_2_step, + &ux_masstransfer_3_step, &ux_masstransfer_4_step, + &ux_masstransfer_5_step, &ux_masstransfer_6_step, + &ux_masstransfer_7_step, &ux_masstransfer_8_step, + &ux_masstransfer_9_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_set_ac_script_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Set account script", + }); +UX_STEP_NOCB(ux_set_ac_script_2_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_set_ac_script_3_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_set_ac_script_4_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_set_ac_script_5_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_set_ac_script_6_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_set_ac_script_7_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_set_ac_script_flow, &ux_set_ac_script_1_step, + &ux_set_ac_script_2_step, &ux_set_ac_script_3_step, + &ux_set_ac_script_4_step, &ux_set_ac_script_5_step, + &ux_set_ac_script_6_step, &ux_set_ac_script_7_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_set_as_script_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Set asset script", + }); +UX_STEP_NOCB(ux_set_as_script_2_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_set_as_script_3_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_set_as_script_4_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_set_as_script_5_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_set_as_script_6_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_set_as_script_7_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_set_as_script_8_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_set_as_script_flow, &ux_set_as_script_1_step, + &ux_set_as_script_2_step, &ux_set_as_script_3_step, + &ux_set_as_script_4_step, &ux_set_as_script_5_step, + &ux_set_as_script_6_step, &ux_set_as_script_7_step, + &ux_set_as_script_8_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_sponsorship_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Fee sponsoring", + }); +UX_STEP_NOCB(ux_sponsorship_2_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_sponsorship_3_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_sponsorship_4_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_sponsorship_5_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_sponsorship_6_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_sponsorship_7_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_sponsorship_8_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_sponsorship_9_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_sponsorship_flow, &ux_sponsorship_1_step, &ux_sponsorship_2_step, + &ux_sponsorship_3_step, &ux_sponsorship_4_step, &ux_sponsorship_5_step, + &ux_sponsorship_6_step, &ux_sponsorship_7_step, &ux_sponsorship_8_step, + &ux_sponsorship_9_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_update_asset_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Update asset info", + }); +UX_STEP_NOCB(ux_update_asset_2_step, bnnn_paging, + { + .title = "Asset", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_update_asset_3_step, bnnn_paging, + { + .title = "Name", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_update_asset_4_step, bnnn_paging, + { + .title = "Description", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB(ux_update_asset_5_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_update_asset_6_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_update_asset_7_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); + +UX_STEP_NOCB(ux_update_asset_8_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_update_asset_9_step, pbb, + io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_update_asset_10_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_update_asset_flow, &ux_update_asset_1_step, &ux_update_asset_2_step, + &ux_update_asset_3_step, &ux_update_asset_4_step, + &ux_update_asset_5_step, &ux_update_asset_6_step, + &ux_update_asset_7_step, &ux_update_asset_8_step, + &ux_update_asset_9_step, &ux_update_asset_10_step); + +////////////////////////////////////////////////////////////////////// +/*UX_STEP_NOCB(ux_invoke_1_step, pnn, + { + &C_icon_eye, + "Confirm", + "Script invocation", + }); +UX_STEP_NOCB(ux_invoke_2_step, bnnn_paging, + { + .title = "dApp", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_invoke_3_step, bnnn_paging, + { + .title = "Function", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB_INIT( + ux_invoke_4_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line3, + sizeof(tmp_ctx.signing_context.ui.line2)), + { + .title = "Payment amount", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB_INIT( + ux_invoke_7_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, + sizeof(tmp_ctx.signing_context.ui.line4)), + { + .title = "Attachment", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); +UX_STEP_NOCB_INIT( + ux_invoke_7_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, + sizeof(tmp_ctx.signing_context.ui.line4)), + { + .title = "Attachment", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); +UX_STEP_NOCB_INIT( + ux_invoke_7_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, + sizeof(tmp_ctx.signing_context.ui.line4)), + { + .title = "Attachment", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); +UX_STEP_NOCB(ux_invoke_8_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); +UX_STEP_NOCB(ux_invoke_9_step, bnnn_paging, + { + .title = "Transaction Id", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_invoke_10_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_invoke_11_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_invoke_flow, &ux_invoke_1_step, &ux_invoke_2_step, + &ux_invoke_3_step, &ux_invoke_4_step, &ux_invoke_5_step, + &ux_invoke_6_step, &ux_invoke_7_step, &ux_invoke_8_step, + &ux_invoke_9_step, &ux_invoke_10_step, &ux_invoke_11_step); +*/ +////////////////////////////////////////////////////////////////////// + UX_STEP_NOCB(ux_verify_transaction_1_step, bnnn_paging, - {.title = "Confirm", .text = (const char *)ui_context.line1}); + {.title = "Confirm", + .text = (const char *)tmp_ctx.signing_context.ui.line1}); UX_STEP_NOCB(ux_verify_transaction_2_step, bnnn_paging, { - .title = (const char *)ui_context.line2, - .text = (const char *)ui_context.line3, + .title = (const char *)tmp_ctx.signing_context.ui.line2, + .text = (const char *)tmp_ctx.signing_context.ui.line3, }); UX_STEP_NOCB(ux_verify_transaction_3_step, bnnn_paging, { .title = "From", - .text = (const char *)ui_context.line4, + .text = (const char *)tmp_ctx.signing_context.ui.from, }); UX_STEP_VALID(ux_verify_transaction_4_step, pbb, io_seproxyhal_touch_sign_approve(NULL), diff --git a/src/ui/print_amount.c b/src/ui/print_amount.c new file mode 100644 index 00000000..8851613b --- /dev/null +++ b/src/ui/print_amount.c @@ -0,0 +1,64 @@ +/******************************************************************************* + * Waves Platform Wallet App for Nano Ledger devices + * Copyright (c) 2017-2020 Sergey Tolmachev (Tolsi) + * + * Based on Sample code provided (c) 2016 Ledger and + * (c) 2017-2018 Jake B. (Burstcoin app) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#include "print_amount.h" + +bool print_amount(uint64_t amount, int decimals, unsigned char *out, + uint8_t len) { + uint64_t dVal = amount; + int i, j; + + if (decimals == 0) + decimals--; + + os_memset(tmp_ctx.signing_context.ui.tmp, 0, len); + for (i = 0; dVal > 0 || i < decimals + 2; i++) { + if (dVal > 0) { + tmp_ctx.signing_context.ui.tmp[i] = (char)((dVal % 10) + '0'); + dVal /= 10; + } else { + tmp_ctx.signing_context.ui.tmp[i] = '0'; + } + if (i == decimals - 1) { + i += 1; + tmp_ctx.signing_context.ui.tmp[i] = '.'; + } + if (i >= len) { + return false; + } + } + // reverse order + for (i -= 1, j = 0; i >= 0 && j < len - 1; i--, j++) { + out[j] = tmp_ctx.signing_context.ui.tmp[i]; + } + if (decimals > 0) { + // strip trailing 0s + for (j -= 1; j > 0; j--) { + if (out[j] != '0') + break; + } + j += 1; + if (out[j - 1] == '.') + j -= 1; + } + + out[j] = '\0'; + return true; +} \ No newline at end of file diff --git a/src/ui/print_amount.h b/src/ui/print_amount.h index c3df0a10..ed6a36f0 100644 --- a/src/ui/print_amount.h +++ b/src/ui/print_amount.h @@ -21,48 +21,10 @@ #ifndef __PRINT_AMOUNT_H__ #define __PRINT_AMOUNT_H__ +#include "../main.h" +#include "os.h" // borrowed from the Stellar wallet code and modified bool print_amount(uint64_t amount, int decimals, unsigned char *out, - uint8_t len) { - uint64_t dVal = amount; - int i, j; - - if (decimals == 0) - decimals--; - - memset(ui_context.tmp, 0, len); - for (i = 0; dVal > 0 || i < decimals + 2; i++) { - if (dVal > 0) { - ui_context.tmp[i] = (char)((dVal % 10) + '0'); - dVal /= 10; - } else { - ui_context.tmp[i] = '0'; - } - if (i == decimals - 1) { - i += 1; - ui_context.tmp[i] = '.'; - } - if (i >= len) { - return false; - } - } - // reverse order - for (i -= 1, j = 0; i >= 0 && j < len - 1; i--, j++) { - out[j] = ui_context.tmp[i]; - } - if (decimals > 0) { - // strip trailing 0s - for (j -= 1; j > 0; j--) { - if (out[j] != '0') - break; - } - j += 1; - if (out[j - 1] == '.') - j -= 1; - } - - out[j] = '\0'; - return true; -} + uint8_t len); #endif \ No newline at end of file diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c new file mode 100644 index 00000000..92fe5ff5 --- /dev/null +++ b/src/ui/transactions/protobuf.c @@ -0,0 +1,271 @@ +/******************************************************************************* + * Waves Platform Wallet App for Nano Ledger devices + * Copyright (c) 2017-2020 Vladislav Petushkov + * + * Based on Sample code provided (c) 2016 Ledger and + * (c) 2017-2018 Jake B. (Burstcoin app) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#include "protobuf.h" +#include "../ui.h" +#include "../print_amount.h" +#include "../../crypto/waves.h" + +bool waves_Recipient_callback(pb_istream_t *istream, pb_ostream_t *ostream, + const pb_field_t *field) { + if (istream) { + int len = istream->bytes_left; + unsigned char buff[len]; + if (!pb_read(istream, buff, (size_t)istream->bytes_left)) { + return false; + } + if (field->tag == waves_Recipient_public_key_hash_tag) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, buff, len); + tmp_ctx.signing_context.ui.pkhash = true; + } else if (field->tag == waves_Recipient_alias_tag) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, buff, len); + } + } + return true; +} + +bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { + size_t length = 45; + int len = stream->bytes_left; + unsigned char buff[len]; + if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + return false; + } + if (len == 32) { + if (!b58enc((char *)*arg, &length, (const void *)buff, 32)) { + return false; + } + } else { + os_memmove((char *)*arg, WAVES_CONST, 5); + } + return true; +} + +bool from_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { + unsigned char buff[32]; + + if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + return false; + } + os_memmove((char *)*arg, buff, 32); + return true; +} + +bool string_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + int strlen = stream->bytes_left; + unsigned char buff[strlen]; + if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + return false; + } + os_memmove((char *)*arg, buff, strlen); + return true; +} + +bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { + int strlen = stream->bytes_left; + if (strlen > 41) { + size_t length = 41; + unsigned char buff[45]; + size_t left = stream->bytes_left - length; + if (!pb_read(stream, buff, length)) { + return false; + } + if (!pb_read(stream, NULL, left)) { + return false; + } + os_memmove((char *)&buff[41], &"...\0", 4); + os_memmove((char *)*arg, buff, 45); + } else { + unsigned char buff[strlen]; + if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + return false; + } + os_memmove((char *)*arg, buff, strlen); + } + return true; +} + +/*bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, +void **arg) { + //unsigned char buff[258]; + + return true; +}*/ + +bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + if (field->tag == waves_Transaction_transfer_tag) { + waves_TransferTransactionData *tx = field->pData; + tx->amount.asset_id.funcs.decode = asset_callback; + tx->amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + tx->attachment.funcs.decode = text_callback; + tx->attachment.arg = &tmp_ctx.signing_context.ui.line4; + } else if (field->tag == waves_Transaction_issue_tag) { + waves_IssueTransactionData *tx = field->pData; + tx->name.funcs.decode = string_callback; + tx->name.arg = &tmp_ctx.signing_context.ui.line1; + tx->description.funcs.decode = text_callback; + tx->description.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_reissue_tag) { + waves_ReissueTransactionData *tx = field->pData; + tx->asset_amount.asset_id.funcs.decode = asset_callback; + tx->asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_burn_tag) { + waves_BurnTransactionData *tx = field->pData; + tx->asset_amount.asset_id.funcs.decode = asset_callback; + tx->asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_lease_cancel_tag) { + waves_LeaseCancelTransactionData *tx = field->pData; + tx->lease_id.funcs.decode = asset_callback; + tx->lease_id.arg = &tmp_ctx.signing_context.ui.line1; + } else if (field->tag == waves_Transaction_create_alias_tag) { + waves_CreateAliasTransactionData *tx = field->pData; + tx->alias.funcs.decode = string_callback; + tx->alias.arg = &tmp_ctx.signing_context.ui.line1; + } else if (field->tag == waves_Transaction_mass_transfer_tag) { + waves_MassTransferTransactionData *tx = field->pData; + tx->asset_id.funcs.decode = asset_callback; + tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx->attachment.funcs.decode = text_callback; + tx->attachment.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_set_asset_script_tag) { + waves_SetAssetScriptTransactionData *tx = field->pData; + tx->asset_id.funcs.decode = asset_callback; + tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; + } else if (field->tag == waves_Transaction_sponsor_fee_tag) { + waves_SponsorFeeTransactionData *tx = field->pData; + tx->min_fee.asset_id.funcs.decode = asset_callback; + tx->min_fee.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_update_asset_info_tag) { + waves_UpdateAssetInfoTransactionData *tx = field->pData; + tx->asset_id.funcs.decode = asset_callback; + tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx->name.funcs.decode = string_callback; + tx->name.arg = &tmp_ctx.signing_context.ui.line2; + tx->description.funcs.decode = text_callback; + tx->description.arg = &tmp_ctx.signing_context.ui.line3; + } /*else if (field->tag == waves_Transaction_invoke_script_tag) { + waves_InvokeScriptTransactionData *tx = field->pData; + tx->function_call.funcs.decode = function_call_callback; + }*/ + return true; +} + +void make_transfer_ui(waves_Transaction *tx) { + print_amount(tx->data.transfer.amount.amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); +} + +void make_reissue_ui(waves_Transaction *tx) { + print_amount(tx->data.reissue.asset_amount.amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + if (tx->data.reissue.reissuable == true) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", + 5); + } else { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"False\0", + 6); + } +} + +void make_issue_ui(waves_Transaction *tx) { + snprintf((char *)tmp_ctx.signing_context.ui.line4, + sizeof(tmp_ctx.signing_context.ui.line4), "%d", + tx->data.issue.decimals); + print_amount(tx->data.issue.amount, (unsigned char)tx->data.issue.decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line3, 20); + if (tx->data.issue.reissuable == true) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"True\0", + 5); + } else { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"False\0", + 6); + } +} + +void make_burn_ui(waves_Transaction *tx) { + print_amount(tx->data.burn.asset_amount.amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); +} + +void make_start_leasing_ui(waves_Transaction *tx) { + print_amount(tx->data.lease.amount, tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); +} + +void make_sponsorship_ui(waves_Transaction *tx) { + print_amount(tx->data.sponsor_fee.min_fee.amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); +} + +/*void make_invoke_ui(waves_Transaction *tx) { + //if(tx->data.invoke_script.payments_count > 0) { + //print_amount(tx->data.invoke_script.payments[0].amount, +tmp_ctx.signing_context.amount_decimals, (unsigned char +*)tmp_ctx.signing_context.ui.line3, 20); + //} + PRINTF("1: %s\n", tmp_ctx.signing_context.ui.line1); + PRINTF("2: %s\n", tmp_ctx.signing_context.ui.line2); + PRINTF("3: %s\n", tmp_ctx.signing_context.ui.line3); +}*/ + +void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size) { + uint8_t status; + waves_Transaction tx = waves_Transaction_init_default; + tx.cb_data.funcs.decode = transaction_data_callback; + tx.sender_public_key.funcs.decode = from_callback; + tx.sender_public_key.arg = &tmp_ctx.signing_context.ui.from; + tx.fee.asset_id.funcs.decode = asset_callback; + tx.fee.asset_id.arg = &tmp_ctx.signing_context.ui.fee_asset; + + pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, + total_buffer_size); + status = pb_decode(&stream, waves_Transaction_fields, &tx); + if (!status) { + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + THROW(0x6D00); + } + print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); + unsigned char tx_type = tmp_ctx.signing_context.data_type; + if (tx_type == 3) { + make_issue_ui(&tx); + } else if (tx_type == 4) { + make_transfer_ui(&tx); + } else if (tx_type == 5) { + make_reissue_ui(&tx); + } else if (tx_type == 6) { + make_burn_ui(&tx); + } else if (tx_type == 8) { + make_start_leasing_ui(&tx); + } else if (tx_type == 14) { + make_sponsorship_ui(&tx); + } else if (tx_type == 16) { + // make_invoke_ui(&tx); + } + tmp_ctx.signing_context.step = 7; + tmp_ctx.signing_context.ui.finished = true; +} diff --git a/src/ui/transactions/protobuf.h b/src/ui/transactions/protobuf.h new file mode 100644 index 00000000..688a6dae --- /dev/null +++ b/src/ui/transactions/protobuf.h @@ -0,0 +1,34 @@ +/******************************************************************************* + * Waves Platform Wallet App for Nano Ledger devices + * Copyright (c) 2017-2020 Vladislav Petushkov + * + * Based on Sample code provided (c) 2016 Ledger and + * (c) 2017-2018 Jake B. (Burstcoin app) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#ifndef __PROTOBUF_H__ +#define __PROTOBUF_H__ + +#include +#include "../../main.h" +#include "../../nanopb/pb.h" +#include "../../nanopb/pb_decode.h" +#include "../../nanopb/pb_custom.h" +#include "../../nanopb_stubs/transaction.pb.h" + +void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size); + +#endif \ No newline at end of file diff --git a/src/ui/transactions/transfer.c b/src/ui/transactions/transfer.c index c1fb3ba6..b8b3011f 100644 --- a/src/ui/transactions/transfer.c +++ b/src/ui/transactions/transfer.c @@ -21,174 +21,174 @@ #include "transfer.h" #include "../../main.h" #include "../ui.h" -#include "../print_amount.h" #include "../../crypto/waves.h" +#include "../print_amount.h" void update_transfer_wait_in_buffer() { - ui_context.buffer_used = 0; - switch (ui_context.step) { + tmp_ctx.signing_context.ui.byte.buffer_used = 0; + switch (tmp_ctx.signing_context.ui.byte.step) { case 2: case 4: case 9: - ui_context.wait_in_buffer = 1; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 1; break; case 11: - ui_context.wait_in_buffer = 4; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 4; break; case 13: - ui_context.wait_in_buffer = 2; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 2; break; case 6: case 7: case 8: - ui_context.wait_in_buffer = 8; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 8; break; case 10: // use first byte from step 9 - ui_context.chunk_used -= 1; - ui_context.wait_in_buffer = 26; + tmp_ctx.signing_context.ui.byte.chunk_used -= 1; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 26; break; case 1: case 3: case 5: - ui_context.wait_in_buffer = 32; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 32; break; case 12: - ui_context.wait_in_buffer = ui_context.alias_size; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = + tmp_ctx.signing_context.ui.byte.alias_size; break; case 14: - ui_context.wait_in_buffer = ui_context.attachment_size; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = + tmp_ctx.signing_context.ui.byte.attachment_size; break; case 15: // last - ui_context.wait_in_buffer = 0; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 0; break; } } void build_transfer_ui_step(bool is_last) { - uint8_t chunk_data_start_index = 5; uint8_t chunk_data_size = G_io_apdu_buffer[4]; + uint8_t chunk_data_start_index = 5; - if (tmp_ctx.signing_context.chunk == 0) { - chunk_data_start_index += 28; - chunk_data_size -= 28; - } - - if (ui_context.wait_in_buffer > 0) { + if (tmp_ctx.signing_context.ui.byte.wait_in_buffer > 0) { try_to_fill_buffer(chunk_data_start_index, chunk_data_size); } - if (ui_context.wait_in_buffer == 0 && !ui_context.finished) { + if (tmp_ctx.signing_context.ui.byte.wait_in_buffer == 0 && + !tmp_ctx.signing_context.ui.finished) { size_t length = 45; - bool is_flag_set = ui_context.buffer[0] == 1; + bool is_flag_set = tmp_ctx.signing_context.ui.byte.buffer[0] == 1; uint64_t amount = 0; uint64_t fee = 0; - PRINTF("build_ui_step step %d\n", ui_context.step); + PRINTF("build_ui_step step %d\n", tmp_ctx.signing_context.ui.byte.step); - switch (ui_context.step) { + switch (tmp_ctx.signing_context.ui.byte.step) { case 0: // type - ui_context.chunk_used = 1; + tmp_ctx.signing_context.ui.byte.chunk_used = + tmp_ctx.signing_context.chunk_used + 1; // skip version if (tmp_ctx.signing_context.data_version == 2) { - ui_context.chunk_used += 1; + tmp_ctx.signing_context.ui.byte.chunk_used += 1; } - ui_context.step = 1; + tmp_ctx.signing_context.ui.byte.step = 1; update_transfer_wait_in_buffer(); break; case 1: // sender public key 32 bytes - waves_public_key_to_address((const unsigned char *)ui_context.buffer, - tmp_ctx.signing_context.network_byte, - (unsigned char *)ui_context.line7); - - ui_context.step = 2; + os_memmove(&tmp_ctx.signing_context.ui.from, + tmp_ctx.signing_context.ui.byte.buffer, 32); + tmp_ctx.signing_context.ui.byte.step = 2; update_transfer_wait_in_buffer(); break; case 2: // amount asset flag if (is_flag_set) { - ui_context.step = 3; + tmp_ctx.signing_context.ui.byte.step = 3; } else { - os_memmove((char *)ui_context.line2, WAVES_CONST, 5); - ui_context.step = 4; + os_memmove((char *)tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); + tmp_ctx.signing_context.ui.byte.step = 4; } update_transfer_wait_in_buffer(); break; case 3: // amount asset - if (!b58enc((char *)ui_context.line2, &length, - (const void *)ui_context.buffer, 32)) { + if (!b58enc((char *)tmp_ctx.signing_context.ui.line2, &length, + (const void *)tmp_ctx.signing_context.ui.byte.buffer, 32)) { return THROW(SW_CONDITIONS_NOT_SATISFIED); } - ui_context.step = 4; + tmp_ctx.signing_context.ui.byte.step = 4; update_transfer_wait_in_buffer(); break; case 4: // fee asset flag if (is_flag_set) { - ui_context.step = 5; + tmp_ctx.signing_context.ui.byte.step = 5; } else { - os_memmove((char *)ui_context.line5, WAVES_CONST, 5); - ui_context.step = 6; + os_memmove((char *)tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, + 5); + tmp_ctx.signing_context.ui.byte.step = 6; } update_transfer_wait_in_buffer(); break; case 5: // fee asset - if (!b58enc((char *)ui_context.line5, &length, - (const void *)ui_context.buffer, 32)) { + if (!b58enc((char *)tmp_ctx.signing_context.ui.fee_asset, &length, + (const void *)tmp_ctx.signing_context.ui.byte.buffer, 32)) { return THROW(SW_CONDITIONS_NOT_SATISFIED); } - ui_context.step = 6; + tmp_ctx.signing_context.ui.byte.step = 6; update_transfer_wait_in_buffer(); break; case 6: // timestamp, skip it - ui_context.step = 7; + tmp_ctx.signing_context.ui.byte.step = 7; update_transfer_wait_in_buffer(); break; case 7: // amount - copy_in_reverse_order((unsigned char *)&amount, - (const unsigned char *)ui_context.buffer, 8); + copy_in_reverse_order( + (unsigned char *)&amount, + (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, 8); print_amount(amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)ui_context.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); - ui_context.step = 8; + tmp_ctx.signing_context.ui.byte.step = 8; update_transfer_wait_in_buffer(); break; case 8: // fee - copy_in_reverse_order((unsigned char *)&fee, - (const unsigned char *)ui_context.buffer, 8); + copy_in_reverse_order( + (unsigned char *)&fee, + (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, 8); print_amount(fee, tmp_ctx.signing_context.fee_decimals, - (unsigned char *)ui_context.line4, 20); + (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); - ui_context.step = 9; + tmp_ctx.signing_context.ui.byte.step = 9; update_transfer_wait_in_buffer(); break; case 9: // address or alias flag is a part of address - if (ui_context.buffer[0] == 1) { - ui_context.step = 10; - } else if (ui_context.buffer[0] == 2) { - ui_context.step = 11; + if (tmp_ctx.signing_context.ui.byte.buffer[0] == 1) { + tmp_ctx.signing_context.ui.byte.step = 10; + } else if (tmp_ctx.signing_context.ui.byte.buffer[0] == 2) { + tmp_ctx.signing_context.ui.byte.step = 11; } else { return THROW(SW_CONDITIONS_NOT_SATISFIED); } @@ -197,68 +197,66 @@ void build_transfer_ui_step(bool is_last) { break; case 10: // address - if (!b58enc((char *)ui_context.line3, &length, - (const void *)ui_context.buffer, 26)) { + if (!b58enc((char *)tmp_ctx.signing_context.ui.line3, &length, + (const void *)tmp_ctx.signing_context.ui.byte.buffer, 26)) { return THROW(SW_CONDITIONS_NOT_SATISFIED); } - ui_context.step = 13; + tmp_ctx.signing_context.ui.byte.step = 13; update_transfer_wait_in_buffer(); break; case 11: // alias len // also skip address scheme byte (first 2) - copy_in_reverse_order((unsigned char *)&ui_context.alias_size, - (unsigned char *)&ui_context.buffer[2], 2); + copy_in_reverse_order( + (unsigned char *)&tmp_ctx.signing_context.ui.byte.alias_size, + (unsigned char *)&tmp_ctx.signing_context.ui.byte.buffer[2], 2); - ui_context.step = 12; + tmp_ctx.signing_context.ui.byte.step = 12; update_transfer_wait_in_buffer(); break; case 12: // alias - os_memmove((unsigned char *)ui_context.line3, - (const unsigned char *)ui_context.buffer, - ui_context.alias_size); + os_memmove((unsigned char *)tmp_ctx.signing_context.ui.line3, + (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, + tmp_ctx.signing_context.ui.byte.alias_size); - ui_context.step = 13; + tmp_ctx.signing_context.ui.byte.step = 13; update_transfer_wait_in_buffer(); break; case 13: // attachment size in bytes - copy_in_reverse_order((unsigned char *)&ui_context.attachment_size, - (unsigned char *)ui_context.buffer, 2); + copy_in_reverse_order( + (unsigned char *)&tmp_ctx.signing_context.ui.byte.attachment_size, + (unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, 2); - ui_context.step = 14; + tmp_ctx.signing_context.ui.byte.step = 14; update_transfer_wait_in_buffer(); break; case 14: // attachment - if (ui_context.attachment_size > 41) { - os_memmove((unsigned char *)&ui_context.line6[41], &"...\0", 4); - ui_context.attachment_size = 41; + if (tmp_ctx.signing_context.ui.byte.attachment_size > 41) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line4[41], + &"...\0", 4); + tmp_ctx.signing_context.ui.byte.attachment_size = 41; } - os_memmove((unsigned char *)ui_context.line6, - (const unsigned char *)ui_context.buffer, - ui_context.attachment_size); + os_memmove((unsigned char *)tmp_ctx.signing_context.ui.line4, + (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, + tmp_ctx.signing_context.ui.byte.attachment_size); - ui_context.step = 15; + tmp_ctx.signing_context.ui.byte.step = 15; update_transfer_wait_in_buffer(); break; case 15: if (is_last) { - size_t length = 45; - // id should be calculated on sign step - if (!b58enc((char *)ui_context.line8, &length, - (const void *)&ui_context.id, 32)) { - return THROW(SW_CONDITIONS_NOT_SATISFIED); - } - ui_context.finished = true; + tmp_ctx.signing_context.ui.finished = true; + tmp_ctx.signing_context.step = 7; } break; default: diff --git a/src/ui/ui.c b/src/ui/ui.c index bb2046b6..ff2892c0 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -24,6 +24,8 @@ #include "../main.h" #include "../crypto/waves.h" #include "transactions/transfer.h" +#include "transactions/protobuf.h" +#include "cx.h" #ifdef TARGET_BLUE #include "blue/ui_menus_blue.h" @@ -41,9 +43,6 @@ enum UI_STATE ui_state; int ux_step, ux_step_count; -bool print_amount(uint64_t amount, int decimals, unsigned char *out, - uint8_t len); - void menu_address_init() { ux_step = 0; ux_step_count = 2; @@ -72,78 +71,76 @@ void ui_idle() { void try_to_fill_buffer(uint8_t chunk_data_start_index, uint8_t chunk_data_size) { - uint32_t chunk_data_left = chunk_data_size - ui_context.chunk_used; + uint32_t chunk_data_left = + chunk_data_size - tmp_ctx.signing_context.ui.byte.chunk_used; uint32_t step_read_bytes_left = - MIN(chunk_data_left, ui_context.wait_in_buffer); - if (ui_context.wait_in_buffer <= 0 || - chunk_data_start_index + ui_context.chunk_used > 150) { + MIN(chunk_data_left, tmp_ctx.signing_context.ui.byte.wait_in_buffer); + if (tmp_ctx.signing_context.ui.byte.wait_in_buffer <= 0 || + chunk_data_start_index + tmp_ctx.signing_context.ui.byte.chunk_used > + 150) { return THROW(EXCEPTION_OVERFLOW); } - os_memmove((unsigned char *)&ui_context.buffer[ui_context.buffer_used], - &G_io_apdu_buffer[chunk_data_start_index + ui_context.chunk_used], + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.byte + .buffer[tmp_ctx.signing_context.ui.byte.buffer_used], + &G_io_apdu_buffer[chunk_data_start_index + + tmp_ctx.signing_context.ui.byte.chunk_used], step_read_bytes_left); - ui_context.chunk_used += step_read_bytes_left; - ui_context.buffer_used += step_read_bytes_left; - ui_context.wait_in_buffer -= step_read_bytes_left; + tmp_ctx.signing_context.ui.byte.chunk_used += step_read_bytes_left; + tmp_ctx.signing_context.ui.byte.buffer_used += step_read_bytes_left; + tmp_ctx.signing_context.ui.byte.wait_in_buffer -= step_read_bytes_left; } void build_other_data_ui() { unsigned char tx_type = tmp_ctx.signing_context.data_type; // just one step here - os_memmove(&ui_context.line2, &"Transaction Id\0", 15); + os_memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Id\0", 15); if (tx_type == 3) { - os_memmove(&ui_context.line1, &"issue\0", 6); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"issue\0", 6); } else if (tx_type == 4) { - os_memmove(&ui_context.line1, &"transfer\0", 9); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"transfer\0", 9); } else if (tx_type == 5) { - os_memmove(&ui_context.line1, &"reissue\0", 8); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"reissue\0", 8); } else if (tx_type == 6) { - os_memmove(&ui_context.line1, &"burn\0", 5); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"burn\0", 5); } else if (tx_type == 8) { - os_memmove(&ui_context.line1, &"start leasing\0", 14); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"start leasing\0", 14); } else if (tx_type == 9) { - os_memmove(&ui_context.line1, &"cancel leasing\0", 15); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"cancel leasing\0", 15); } else if (tx_type == 10) { - os_memmove(&ui_context.line2, &"Transaction Hash\0", 17); - os_memmove(&ui_context.line1, &"creating an alias\0", 18); + os_memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Hash\0", 17); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"creating an alias\0", 18); } else if (tx_type == 11) { - os_memmove(&ui_context.line1, &"mass transfer\0", 14); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"mass transfer\0", 14); } else if (tx_type == 12) { - os_memmove(&ui_context.line1, &"data\0", 5); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); } else if (tx_type == 13) { - os_memmove(&ui_context.line1, &"set script\0", 11); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"set script\0", 11); } else if (tx_type == 14) { - os_memmove(&ui_context.line1, &"sponsorship\0", 12); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"sponsorship\0", 12); } else if (tx_type == 15) { - os_memmove(&ui_context.line1, &"asset script\0", 13); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"asset script\0", 13); } else if (tx_type == 16) { - os_memmove(&ui_context.line1, &"script invocation\0", 18); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"script invocation\0", 18); } else if (tx_type == 17) { - os_memmove(&ui_context.line1, &"update asset info\0", 18); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"update asset info\0", 18); } else if (tx_type > 200) { // type byte >200 are 'reserved', it will not be signed - os_memmove(&ui_context.line2, &"Hash\0", 5); + os_memmove(&tmp_ctx.signing_context.ui.line2, &"Hash\0", 5); if (tx_type == 252) { - os_memmove(&ui_context.line1, &"order\0", 6); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"order\0", 6); } else if (tx_type == 253) { - os_memmove(&ui_context.line1, &"data\0", 5); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); } else if (tx_type == 254) { - os_memmove(&ui_context.line1, &"request\0", 8); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"request\0", 8); } else if (tx_type == 255) { - os_memmove(&ui_context.line1, &"message\0", 8); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"message\0", 8); } else { - os_memmove(&ui_context.line1, &"something\0", 10); + os_memmove(&tmp_ctx.signing_context.ui.line1, &"something\0", 10); } } - if (strlen((const char *)ui_context.line1) == 0) { - os_memmove(&ui_context.line1, &"transaction\0", 12); - } - // id should be calculated on sign step - size_t length = 45; - if (!b58enc((char *)ui_context.line3, &length, (const void *)&ui_context.id, - 32)) { - THROW(SW_CONDITIONS_NOT_SATISFIED); + if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { + os_memmove(&tmp_ctx.signing_context.ui.line1, &"transaction\0", 12); } // Get the public key and return it. @@ -154,24 +151,47 @@ void build_other_data_ui() { THROW(INVALID_PARAMETER); } - waves_public_key_to_address( - public_key.W, tmp_ctx.signing_context.network_byte, ui_context.line4); + os_memmove(&tmp_ctx.signing_context.ui.from, public_key.W, 32); + tmp_ctx.signing_context.ui.finished = true; } void make_allowed_ui_steps(bool is_last) { + uint32_t start_index; PRINTF("make_allowed_ui_steps start\n"); - if (tmp_ctx.signing_context.data_type == 4) { - uint8_t chunk_data_size = G_io_apdu_buffer[4]; - if (tmp_ctx.signing_context.chunk == 0) { - chunk_data_size -= 28; + if (tmp_ctx.signing_context.data_version > 2) { + if (tmp_ctx.signing_context.ui.finished != true) { + build_protobuf_ui( + &tmp_ctx.signing_context.ui.proto, + G_io_apdu_buffer + 5 + tmp_ctx.signing_context.chunk_used, + G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used, + tmp_ctx.signing_context.data_size); + } else { + THROW(SW_INS_NOT_SUPPORTED); } - while ( - (chunk_data_size - ui_context.chunk_used > 0 && ui_context.step < 15) || - (ui_context.step == 15 && !ui_context.finished && is_last)) { - build_transfer_ui_step(is_last); + } else { + if (tmp_ctx.signing_context.ui.byte.step == 0) { + start_index = tmp_ctx.signing_context.chunk_used; + } else { + start_index = tmp_ctx.signing_context.ui.byte.chunk_used; } - } else if (is_last) { - build_other_data_ui(); + + if (tmp_ctx.signing_context.data_type == 4) { + uint8_t chunk_data_size = G_io_apdu_buffer[4]; + while ( + (chunk_data_size - tmp_ctx.signing_context.ui.byte.chunk_used > 0 && + tmp_ctx.signing_context.ui.byte.step < 15) || + (tmp_ctx.signing_context.ui.byte.step == 15 && + !tmp_ctx.signing_context.ui.finished && is_last)) { + build_transfer_ui_step(is_last); + } + } else if (is_last) { + build_other_data_ui(); + tmp_ctx.signing_context.step = 7; + } + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, + G_io_apdu_buffer + 5 + start_index, + G_io_apdu_buffer[4] - start_index, NULL, 0); + tmp_ctx.signing_context.ui.byte.chunk_used = 0; } PRINTF("make_allowed_ui_steps end\n"); } @@ -202,6 +222,106 @@ void show_sign_ui() { } } +void show_sign_protobuf_ui() { + unsigned char tx_type = tmp_ctx.signing_context.data_type; + ux_step = 0; + ui_state = UI_VERIFY; + if (tx_type == 3) { + ux_step_count = 10; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_issue_blue, NULL); +#else + ux_flow_init(0, ux_issue_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 4) { + ux_step_count = 9; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_transfer_blue, NULL); +#else + ux_flow_init(0, ux_transfer_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 5) { + ux_step_count = 7; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_reissue_blue, NULL); +#else + ux_flow_init(0, ux_reissue_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 6) { + ux_step_count = 7; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_burn_blue, NULL); +#else + ux_flow_init(0, ux_burn_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 8) { + ux_step_count = 7; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_lease_blue, NULL); +#else + ux_flow_init(0, ux_lease_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 9) { + ux_step_count = 6; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_cancel_lease_blue, NULL); +#else + ux_flow_init(0, ux_cancel_lease_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 10) { + ux_step_count = 6; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_create_alias_blue, NULL); +#else + ux_flow_init(0, ux_create_alias_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 11) { + ux_step_count = 7; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_masstransfer_blue, NULL); +#else + ux_flow_init(0, ux_masstransfer_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 12) { + ux_step_count = 5; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_data_blue, NULL); +#else + ux_flow_init(0, ux_data_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 13) { + ux_step_count = 5; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_set_ac_script_blue, NULL); +#else + ux_flow_init(0, ux_set_ac_script_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 14) { + ux_step_count = 7; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_sponsorship_blue, NULL); +#else + ux_flow_init(0, ux_sponsorship_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 15) { + ux_step_count = 6; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_set_as_script_blue, NULL); +#else + ux_flow_init(0, ux_set_as_script_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 16) { + os_memmove(&tmp_ctx.signing_context.ui.line1, &"script invocation\0", 18); + } else if (tx_type == 17) { + ux_step_count = 8; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_update_asset_blue, NULL); +#else + ux_flow_init(0, ux_update_asset_flow, NULL); +#endif // #if TARGET_ID + } +} + void show_processing() { #if defined(TARGET_BLUE) UX_DISPLAY(ui_processing_blue, NULL); diff --git a/src/ui/ui.h b/src/ui/ui.h index 28751631..8cf6511a 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -46,6 +46,7 @@ extern int ux_step_count; void make_allowed_ui_steps(bool is_last); void show_sign_ui(); +void show_sign_protobuf_ui(); void menu_address_init(); void show_processing(); From 4f2891ca1af68fc2dc009946c141437e91f74847 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Wed, 17 Jun 2020 18:26:55 +0400 Subject: [PATCH 08/26] fix bugs with blue menu --- src/ui/blue/ui_menus_blue.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index c189a66e..6b6e7617 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -3529,7 +3529,7 @@ const bagl_element_t ui_verify_set_as_script_blue[] = { ////////////////////////////////////////////////////////////////////////////// -const bagl_element_t ui_verify_issue_blue[] = { +const bagl_element_t ui_verify_update_asset_blue[] = { {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, 0x000000, 0, 0}, NULL, @@ -4125,10 +4125,18 @@ unsigned int ui_idle_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; } + unsigned int ui_address_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; } + +unsigned int ui_verify_transfer_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + + unsigned int ui_verify_data_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; From e095798c0faeb5865386b2cea801368edf4e410b Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 25 Jun 2020 14:00:06 +0400 Subject: [PATCH 09/26] fixed bug with the fee amount viewing --- Makefile | 2 +- python/ledger-waves.py | 34 ++- src/main.c | 18 +- src/main.h | 26 ++- src/ui/blue/ui_menus_blue.h | 411 +++++++++++++++++++++++++++++++++ src/ui/nanox/ui_menus_nanox.h | 60 +++-- src/ui/transactions/protobuf.c | 89 +++++-- src/ui/ui.c | 7 +- 8 files changed, 575 insertions(+), 72 deletions(-) diff --git a/Makefile b/Makefile index 5fe407f7..a44b6fba 100755 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 0 +DEBUG = 1 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index 981de042..2b416c39 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -23,11 +23,9 @@ import pywaves.crypto as pwcrypto import pywaves as pw import time -import binascii import base64 from amount_pb2 import Amount import transaction_pb2 as tpb -#from transaction_pb2 import Transaction, TransferTransactionData, DataTransactionData, IssueTransactionData, ReissueTransactionData, BurnTransactionData, LeaseTransactionData Attachment from recipient_pb2 import Recipient global dongle @@ -355,12 +353,13 @@ def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=1000 trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, sponsor_fee=sponsorship) return trx.SerializeToString() -def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): +def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amount2, feeAsset='', txFee=100000, timestamp=0, version = 3): if timestamp == 0: timestamp = int(time.time() * 1000) amounts = [] amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) amounts.append(amountTx) + amountTx= Amount(asset_id=base58.b58decode(asset2.assetId), amount=amount2) amounts.append(amountTx) to = Recipient(public_key_hash=base58.b58decode(dapp)) invoke = tpb.InvokeScriptTransactionData(d_app = to, function_call = function, payments = amounts) @@ -410,6 +409,8 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', # tx amount asset decimals binary_data += chr(8) + # tx amount asset decimals 2 + binary_data += chr(0) # fee amount asset decimals binary_data += chr(8) # Tx info @@ -492,7 +493,7 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', print(colors.fg.white + "\t 4. Transfer" + colors.reset) print(colors.fg.white + "\t 5. Reissue" + colors.reset) print(colors.fg.white + "\t 6. Burn" + colors.reset) - print(colors.fg.white + "\t 7. Exchange" + colors.reset) + #print(colors.fg.white + "\t 7. Exchange" + colors.reset) print(colors.fg.white + "\t 8. Lease" + colors.reset) print(colors.fg.white + "\t 9. Lease Cancel" + colors.reset) print(colors.fg.white + "\t 10. Create Alias" + colors.reset) @@ -506,6 +507,7 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', print(colors.fg.white + "\t 0. Exit" + colors.reset) select = raw_input(colors.fg.cyan + "Please select transaction type> " + colors.reset) decimals = 8 # tx amount asset decimals + decimals2 = 0 feeDecimals = 8 #fee amount asset decimals if (select == "3"): decimals = 3 @@ -590,7 +592,7 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', elif (select == "11"): some_transfer_bytes = build_masstransfer_protobuf( '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL, + "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), 10000000, 'privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000', @@ -639,10 +641,22 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', 1526477921829, 3 ) - #elif (select == "16"): - #fname = "function_name" - #function_call = "" - #fcal=chr(1) + chr(9) + chr(1) + fname.encode() + function_call.encode() + elif (select == "16"): + fname = "function_name" + function_call = chr(2) + chr(2) + "argument1".encode() + chr(2) + "argument2".encode() + fcal=chr(1) + chr(9) + chr(1) + struct.pack(">I", len(fname)) + fname.encode() + function_call + decimals = 6 + decimals2 = 8 + some_transfer_bytes = build_invoke_protobuf( + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + fcal, + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + 1000000, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 1000000000, + ) + some_transfer_bytes = base58.b58decode("FgBL1ir521wY8kGhSGQF3Tdxx6UtF46W15hoTCccswWjTRpnM8JE48R8LJZcerjGVNFNwc8W2vY67Uhb6wfH8BHFb5iMzUKAg72MWSriBZo6FGu2YgQaq4JNd4TbteB4ddNMXu7Gi8XMGvH6vLiy4EJWVXHCZWmjow6iJydGi56h6xHriwhmSbxyB81Tad6dUHwsojK7287yrhHpZbH4QMB5ScCuq5HHd4SjSsuMaGY422V12baZFu48NCi5obPEri5JiLzXz51BEuQTQx3gKtikhc92VbpjgHCfEjfxx7gcP2XT5ydTaWR2hYe2Jv9sQzSSbhvfj3Av62rJS9uj5rS1DeAJkJbBWGWzVehqfpRWev7aDwvqtnhzCygSrAGKQoR6k9dCaaRzVJo8Tk1f4gBsdqgwLUofvNTC4nJpzawR8pujoaKVfZwQLYJjsA69dUwhexQXtmEWQjdtsajLbtbakFbEdrcDWgYckvGDYeyyUAinN1Unb9iGJMNGvWDyKiQiCT7WDmgMzCE623xEfrTgEXx45NuuNpGdALcfBi7Fm6JtzGoPhJ7ftsCFMxXvyhBwDUq59L3wBzaXGw4ikNwBrQsFTzmMVCzU2Dixnm9nyuZKoipuqW4B2CwnQGJgrAqhy8CkMtAyZsW1U4AwrZhVQiKVDX8M8P5uYJ2dnCmjSazJnp4k1YSuwm7mFBbcYfqsxVcB6TUUzfqdb4ADh3ULrQacKWdpMGPA3Xnj2kJMuA3GNbwosh7okvRZWaxTjujDx4jkmh2uZtbqMn4BNxdqWqknnLpMupbhU95oUdbxvSxXiLnRQEgmWjkLoavmw5EJQVS7ck3yfkZTkArkPSJZNJo4E9smVgpks1eaUNfKvZkGQuDU2kYqPSgmQ8uLtN1VugeEydaCUFUQWeTbDR2iiWKpCzyTVFmkWi7G5Hg8shUF88DioFZsCGeJooRG5DNa2qvYJ53o2z4owVuxw1K6L3mU8RxY5kcvagoK3PvudxYPvNExKU7iEedLT9dgTgtJ431foD1kLuTDV93wWGm3oiFVW7gvHM9zZdeyqBRF39aQwi1MX3a4nasFdf3RnX1WSAhD6tYA44jNWZ95Cw675UT1SWJb688TpPppiH6eiL8e6uEEevCGKw3zPJ5Vmb325PcotS3BZetZ2fEwfRrW4xcZvRUYkD3uS1yGExpcU8uJNvYybb7padUuU6udtrdoZerxLwjzcfp3gZGUUGwo8C7X9ZRWkCP22jc4d9osKqfvJQQzgnbjJpRvdhM3RZ3gd5CQ9gaVrDkT1ffi9qUeKvUrw18k2Y22NmjfQYKx9b9DfZBye4sYEte4TfFyJmPTEd5RZkwDh9vhzSjx4S3WkfYAzbeETvzap1HsfJC1zKLC5cKnkJPBRei4QAZCMsQo3oqCVFAwFkrKbxhJQAbkaxtEnQs4pG3NqWFMKskYNQjjkuBf1EL9q1X4iM6Jr8ocSjxpXC9NLSyiP4DjCZxhNyWERZvFXmmTgjycpkYzyzGbVtwuLvSBpnPHZysKmHnaPvMiHz9rfrVG9187kdk8RURjH1PsPckJLKPE2ApFz6Qi3Gq5bTWwiij6Hi9eEVUwUWERAZon1PBniWk2cLHAoZpTpViKQWhcR8fWaTLKUVFiMDM6ofserGp9wgabXZAY3vw7daYVEwYzHmsZovgXAnVZCAzUeZaJ7PD8EscWy58ym3dh2NkE33aT5AfZsPFwk9wDU8QA4uut6cDFWd5Ua"); elif (select == "17"): some_transfer_bytes = build_update_asset_protobuf( @@ -666,6 +680,8 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, feeAsset='', # tx amount asset decimals binary_data += chr(decimals) + # tx amount2 asset decimals + binary_data += chr(decimals2) # fee amount asset decimals binary_data += chr(feeDecimals) diff --git a/src/main.c b/src/main.c index 269d45f5..2fe1f02e 100644 --- a/src/main.c +++ b/src/main.c @@ -163,19 +163,20 @@ void make_allowed_sign_steps() { uint8_t chunk_data_size = G_io_apdu_buffer[4]; if (tmp_ctx.signing_context.chunk == 0) { - chunk_data_start_index += 28; - chunk_data_size -= 28; + chunk_data_start_index += 29; + chunk_data_size -= 29; // then there is the bip32 path in the first chunk - first 20 bytes of data read_path_from_bytes(G_io_apdu_buffer + 5, (uint32_t *)tmp_ctx.signing_context.bip32); tmp_ctx.signing_context.amount_decimals = G_io_apdu_buffer[25]; - tmp_ctx.signing_context.fee_decimals = G_io_apdu_buffer[26]; - tmp_ctx.signing_context.data_type = G_io_apdu_buffer[27]; - tmp_ctx.signing_context.data_version = G_io_apdu_buffer[28]; + tmp_ctx.signing_context.amount2_decimals = G_io_apdu_buffer[26]; + tmp_ctx.signing_context.fee_decimals = G_io_apdu_buffer[27]; + tmp_ctx.signing_context.data_type = G_io_apdu_buffer[28]; + tmp_ctx.signing_context.data_version = G_io_apdu_buffer[29]; tmp_ctx.signing_context.data_size = - deserialize_uint32_t(&G_io_apdu_buffer[29]); + deserialize_uint32_t(&G_io_apdu_buffer[30]); } while (tmp_ctx.signing_context.chunk_used < chunk_data_size && @@ -246,7 +247,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.chunk += 1; } else { PRINTF("make_sign_steps start\n"); - show_processing(); + //show_processing(); tmp_ctx.signing_context.step = 1; tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; } @@ -273,6 +274,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } else { make_allowed_ui_steps(false); } + if (tmp_ctx.signing_context.step == 7) { unsigned char third_data_hash[64]; cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, @@ -291,6 +293,8 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, waves_public_key_to_address(tmp_ctx.signing_context.ui.from, tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.from); + + if (tmp_ctx.signing_context.ui.pkhash) { waves_public_key_hash_to_address( tmp_ctx.signing_context.ui.line3, diff --git a/src/main.h b/src/main.h index f6071514..d894df51 100644 --- a/src/main.h +++ b/src/main.h @@ -84,9 +84,13 @@ typedef struct uiProtobuf_t { // for displaying to the user when requesting approval // 44 for address/id and +1 for \0 typedef struct uiContext_t { - unsigned char tmp[10]; + union { + uiByte_t byte; + uiProtobuf_t proto; + }; + unsigned char tmp[20]; unsigned char txid[45]; - unsigned char from[35]; + unsigned char from[45]; unsigned char fee_amount[20]; unsigned char fee_asset[45]; unsigned char line1[45]; @@ -94,19 +98,21 @@ typedef struct uiContext_t { unsigned char line3[45]; unsigned char line4[45]; unsigned char line5[45]; + unsigned char line6[20]; bool pkhash; - cx_blake2b_t hash_ctx; - union { - uiByte_t byte; - uiProtobuf_t proto; - }; bool finished; + cx_blake2b_t hash_ctx; } uiContext_t; // A place to store data during the signing typedef struct signingContext_t { + union { + uiContext_t ui; + streamEddsaContext_t eddsa_context; + }; unsigned char sign_bit; unsigned char amount_decimals; + unsigned char amount2_decimals; unsigned char fee_decimals; unsigned char data_type; unsigned char data_version; @@ -120,11 +126,6 @@ typedef struct signingContext_t { uint32_t data_size; uint32_t chunk_used; uint32_t chunk; - union { - uiContext_t ui; - streamEddsaContext_t eddsa_context; - }; - } signingContext_t; // A place to store data during the confirming the address @@ -148,5 +149,6 @@ void init_sign(); void make_allowed_sign_steps(); uint32_t set_result_get_address(); uint32_t set_result_sign(); +uint32_t deserialize_uint32_t(unsigned char *buffer); #endif \ No newline at end of file diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index 6b6e7617..ff536ee6 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -3845,6 +3845,417 @@ const bagl_element_t ui_verify_update_asset_blue[] = { }; +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_invoke_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 75, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 94, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Script invocation", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "dApp", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Function", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Payment 1 amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line4, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Payment 1 asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Payment 2 amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line6, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Payment 2 asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line5, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 296, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 296, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 309, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Transaction ID", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + const bagl_element_t ui_approval_blue[] = { {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, 0x000000, 0, 0}, diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index dc543e2d..751ff745 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -824,7 +824,7 @@ UX_FLOW(ux_update_asset_flow, &ux_update_asset_1_step, &ux_update_asset_2_step, &ux_update_asset_9_step, &ux_update_asset_10_step); ////////////////////////////////////////////////////////////////////// -/*UX_STEP_NOCB(ux_invoke_1_step, pnn, +UX_STEP_NOCB(ux_invoke_1_step, pnn, { &C_icon_eye, "Confirm", @@ -833,7 +833,7 @@ UX_FLOW(ux_update_asset_flow, &ux_update_asset_1_step, &ux_update_asset_2_step, UX_STEP_NOCB(ux_invoke_2_step, bnnn_paging, { .title = "dApp", - .text = (const char *)tmp_ctx.signing_context.ui.line1, + .text = (const char *)tmp_ctx.signing_context.ui.line3, }); UX_STEP_NOCB(ux_invoke_3_step, bnnn_paging, { @@ -842,53 +842,63 @@ UX_STEP_NOCB(ux_invoke_3_step, bnnn_paging, }); UX_STEP_NOCB_INIT( ux_invoke_4_step, bnnn_paging, - display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line3, - sizeof(tmp_ctx.signing_context.ui.line2)), - { - .title = "Payment amount", - .text = (const char *)tmp_ctx.signing_context.ui.line3, - }); -UX_STEP_NOCB_INIT( - ux_invoke_7_step, bnnn_paging, display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, sizeof(tmp_ctx.signing_context.ui.line4)), { - .title = "Attachment", + .title = "Payment 1 amount", .text = (const char *)tmp_ctx.signing_context.ui.line4, }); UX_STEP_NOCB_INIT( - ux_invoke_7_step, bnnn_paging, - display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, - sizeof(tmp_ctx.signing_context.ui.line4)), + ux_invoke_5_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line1, + sizeof(tmp_ctx.signing_context.ui.line1)), { - .title = "Attachment", - .text = (const char *)tmp_ctx.signing_context.ui.line4, + .title = "Payment 1 asset", + .text = (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB_INIT( + ux_invoke_6_step, bnnn_paging, + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line6, + sizeof(tmp_ctx.signing_context.ui.line6)), + { + .title = "Payment 2 amount", + .text = (const char *)tmp_ctx.signing_context.ui.line6, }); UX_STEP_NOCB_INIT( ux_invoke_7_step, bnnn_paging, - display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line4, - sizeof(tmp_ctx.signing_context.ui.line4)), + display_if_buffer_not_empty((const char *)tmp_ctx.signing_context.ui.line5, + sizeof(tmp_ctx.signing_context.ui.line5)), { - .title = "Attachment", - .text = (const char *)tmp_ctx.signing_context.ui.line4, + .title = "Payment 2 asset", + .text = (const char *)tmp_ctx.signing_context.ui.line5, }); UX_STEP_NOCB(ux_invoke_8_step, bnnn_paging, + { + .title = "Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_invoke_9_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); +UX_STEP_NOCB(ux_invoke_10_step, bnnn_paging, { .title = "From", .text = (const char *)tmp_ctx.signing_context.ui.from, }); -UX_STEP_NOCB(ux_invoke_9_step, bnnn_paging, +UX_STEP_NOCB(ux_invoke_11_step, bnnn_paging, { .title = "Transaction Id", .text = (const char *)tmp_ctx.signing_context.ui.txid, }); -UX_STEP_VALID(ux_invoke_10_step, pbb, io_seproxyhal_touch_sign_approve(NULL), +UX_STEP_VALID(ux_invoke_12_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { &C_icon_validate_14, "Accept", "and send", }); -UX_STEP_VALID(ux_invoke_11_step, pb, io_seproxyhal_cancel(NULL), +UX_STEP_VALID(ux_invoke_13_step, pb, io_seproxyhal_cancel(NULL), { &C_icon_crossmark, "Reject", @@ -897,8 +907,8 @@ UX_STEP_VALID(ux_invoke_11_step, pb, io_seproxyhal_cancel(NULL), UX_FLOW(ux_invoke_flow, &ux_invoke_1_step, &ux_invoke_2_step, &ux_invoke_3_step, &ux_invoke_4_step, &ux_invoke_5_step, &ux_invoke_6_step, &ux_invoke_7_step, &ux_invoke_8_step, - &ux_invoke_9_step, &ux_invoke_10_step, &ux_invoke_11_step); -*/ + &ux_invoke_9_step, &ux_invoke_10_step, &ux_invoke_11_step, + &ux_invoke_12_step, &ux_invoke_13_step); ////////////////////////////////////////////////////////////////////// UX_STEP_NOCB(ux_verify_transaction_1_step, bnnn_paging, diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 92fe5ff5..d79eb5bf 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -103,12 +103,60 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { return true; } -/*bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, +bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - //unsigned char buff[258]; - + unsigned char buff[45]; + uint32_t name_len; + int len = stream->bytes_left; + if (!pb_read(stream, buff, 7)) { // read setting 3 bytes and 4 byte of function name size + return false; + } + len -= 7; + name_len = deserialize_uint32_t(&buff[3]); + if(name_len > 41) { //if function name len is + if (!pb_read(stream, buff, 41)) { // read 41 byte of the name + return false; + } + len -= 41; + os_memmove((char *)&buff[41], &"...\0", 4); + os_memmove((char *)*arg, buff, 45); + if (!pb_read(stream, NULL, len)) { // read last str to null + return false; + } + } else { + if (!pb_read(stream, buff, name_len)) { // read all name str + return false; + } + len -= name_len; + os_memmove((char *)*arg, buff, 45); + if (!pb_read(stream, NULL, len)) { // read setting 3 bytes and 4 byte of function name size + return false; + } + } return true; -}*/ +} + +bool copy_amount(uint64_t amount, int decimals, unsigned char * out) { + return print_amount(amount, decimals, out, 20); +} + +bool amount_callback(pb_istream_t *stream, const pb_field_t *field, +void **arg) { + uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + return copy_amount(value, tmp_ctx.signing_context.amount_decimals, (unsigned char *)*arg); +} + +bool amount2_callback(pb_istream_t *stream, const pb_field_t *field, +void **arg) { + uint64_t value; + if (!pb_decode_varint(stream, &value)) + return false; + return copy_amount(value, tmp_ctx.signing_context.amount2_decimals, (unsigned char *)*arg); +} + + bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { @@ -162,10 +210,18 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, tx->name.arg = &tmp_ctx.signing_context.ui.line2; tx->description.funcs.decode = text_callback; tx->description.arg = &tmp_ctx.signing_context.ui.line3; - } /*else if (field->tag == waves_Transaction_invoke_script_tag) { + } else if (field->tag == waves_Transaction_invoke_script_tag) { waves_InvokeScriptTransactionData *tx = field->pData; tx->function_call.funcs.decode = function_call_callback; - }*/ + tx->function_call.arg = &tmp_ctx.signing_context.ui.line2; + tx->payments[0].asset_id.funcs.decode = asset_callback; + tx->payments[0].asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx->payments[1].asset_id.funcs.decode = asset_callback; + tx->payments[1].asset_id.arg = &tmp_ctx.signing_context.ui.line5; + } else if (field->tag == waves_Transaction_exchange_tag) { + waves_ExchangeTransactionData *tx = field->pData; + + } return true; } @@ -220,16 +276,14 @@ void make_sponsorship_ui(waves_Transaction *tx) { (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); } -/*void make_invoke_ui(waves_Transaction *tx) { - //if(tx->data.invoke_script.payments_count > 0) { - //print_amount(tx->data.invoke_script.payments[0].amount, -tmp_ctx.signing_context.amount_decimals, (unsigned char -*)tmp_ctx.signing_context.ui.line3, 20); - //} - PRINTF("1: %s\n", tmp_ctx.signing_context.ui.line1); - PRINTF("2: %s\n", tmp_ctx.signing_context.ui.line2); - PRINTF("3: %s\n", tmp_ctx.signing_context.ui.line3); -}*/ +void make_invoke_ui(waves_Transaction *tx) { + if(tx->data.invoke_script.payments_count >= 1) { + print_amount(tx->data.invoke_script.payments[0].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line4, 20); + } + if(tx->data.invoke_script.payments_count == 2) { + print_amount(tx->data.invoke_script.payments[1].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line6, 20); + } +} void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, uint16_t total_buffer_size) { @@ -248,6 +302,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } + print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); unsigned char tx_type = tmp_ctx.signing_context.data_type; @@ -264,7 +319,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, } else if (tx_type == 14) { make_sponsorship_ui(&tx); } else if (tx_type == 16) { - // make_invoke_ui(&tx); + make_invoke_ui(&tx); } tmp_ctx.signing_context.step = 7; tmp_ctx.signing_context.ui.finished = true; diff --git a/src/ui/ui.c b/src/ui/ui.c index ff2892c0..b97a4590 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -311,7 +311,12 @@ void show_sign_protobuf_ui() { ux_flow_init(0, ux_set_as_script_flow, NULL); #endif // #if TARGET_ID } else if (tx_type == 16) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"script invocation\0", 18); + ux_step_count = 11; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_invoke_blue, NULL); +#else + ux_flow_init(0, ux_invoke_flow, NULL); +#endif // #if TARGET_ID } else if (tx_type == 17) { ux_step_count = 8; #if defined(TARGET_BLUE) From 75b933ffb5371c241213275ea464e07539022c5b Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 25 Jun 2020 14:00:31 +0400 Subject: [PATCH 10/26] turn off debug --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a44b6fba..5fe407f7 100755 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 1 +DEBUG = 0 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) From 7fd608a6b858f8c445d721154c06da9c2453d91d Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 25 Jun 2020 14:14:01 +0400 Subject: [PATCH 11/26] fix bug with blue button callback --- src/ui/blue/ui_menus_blue.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index ff536ee6..6272770c 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -4609,6 +4609,12 @@ ui_verify_set_as_script_blue_button(unsigned int button_mask, return 0; } +unsigned int +ui_verify_invoke_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + unsigned int ui_verify_update_asset_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { From cfaa4469754c908ba359f141a9570ff5b6b4efd8 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 25 Jun 2020 18:15:07 +0400 Subject: [PATCH 12/26] add test data for blue --- python/ledger-waves.py | 6 +++--- src/ui/transactions/protobuf.c | 5 +---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index 2b416c39..cd5b71bf 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -334,9 +334,9 @@ def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, versi if timestamp == 0: timestamp = int(time.time() * 1000) list = [] - for x in range(3): - k = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) - s = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) + for x in range(1): + k = "j" + str(x) + s = "jjjjjjj" + str(x) dataEntery = tpb.DataTransactionData.DataEntry(key=k, string_value=s ) list.append(dataEntery) data = tpb.DataTransactionData(data = list) diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index d79eb5bf..0ab74b99 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -218,10 +218,7 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, tx->payments[0].asset_id.arg = &tmp_ctx.signing_context.ui.line1; tx->payments[1].asset_id.funcs.decode = asset_callback; tx->payments[1].asset_id.arg = &tmp_ctx.signing_context.ui.line5; - } else if (field->tag == waves_Transaction_exchange_tag) { - waves_ExchangeTransactionData *tx = field->pData; - - } + } return true; } From 68fc3f2d2f729073e2380226199fe6649226135e Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 25 Jun 2020 19:04:52 +0400 Subject: [PATCH 13/26] add some comments and minor fixes --- src/main.c | 6 +++--- src/main.h | 2 +- src/nanopb/pb_custom.c | 5 ++++- src/ui/transactions/protobuf.c | 11 ++++++++++- src/ui/ui.c | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main.c b/src/main.c index 2fe1f02e..627ef7eb 100644 --- a/src/main.c +++ b/src/main.c @@ -247,7 +247,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.chunk += 1; } else { PRINTF("make_sign_steps start\n"); - //show_processing(); + show_processing(); tmp_ctx.signing_context.step = 1; tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; } @@ -275,7 +275,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, make_allowed_ui_steps(false); } - if (tmp_ctx.signing_context.step == 7) { + if (tmp_ctx.signing_context.step == 7) { // all data parsed and prepeared to view unsigned char third_data_hash[64]; cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, third_data_hash, 32); @@ -294,7 +294,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.from); - + // if transaction has from field and it is pubkey hash will convert to address if (tmp_ctx.signing_context.ui.pkhash) { waves_public_key_hash_to_address( tmp_ctx.signing_context.ui.line3, diff --git a/src/main.h b/src/main.h index d894df51..aa1e6787 100644 --- a/src/main.h +++ b/src/main.h @@ -95,7 +95,7 @@ typedef struct uiContext_t { unsigned char fee_asset[45]; unsigned char line1[45]; unsigned char line2[45]; - unsigned char line3[45]; + unsigned char line3[45]; // reserved for recipient if transaction has resipient message unsigned char line4[45]; unsigned char line5[45]; unsigned char line6[20]; diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index c436f6e9..b56874d9 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -99,8 +99,9 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { stream->bytes_left = 0; return false; } - + // fetch next bytes fetch_new_apdu(state); + //creating hash to check view and sign data are the same cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, G_io_apdu_buffer + 5, G_io_apdu_buffer[4], NULL, 0); os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, @@ -111,6 +112,8 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { } } if (state->total_size <= state->total_read) { + // Everything has been received, signal to nanopb that it's time to end + // decoding stream->bytes_left = 0; return false; } diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 0ab74b99..80af4f83 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -23,6 +23,9 @@ #include "../print_amount.h" #include "../../crypto/waves.h" +// function to parse recipient in all transactions +// using autocallback in protofiles +// saving to 3 field bool waves_Recipient_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) { if (istream) { @@ -285,15 +288,19 @@ void make_invoke_ui(waves_Transaction *tx) { void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, uint16_t total_buffer_size) { uint8_t status; + // init variable for parsing waves_Transaction tx = waves_Transaction_init_default; + // set callback for parsing tx data tx.cb_data.funcs.decode = transaction_data_callback; + tx.sender_public_key.funcs.decode = from_callback; tx.sender_public_key.arg = &tmp_ctx.signing_context.ui.from; tx.fee.asset_id.funcs.decode = asset_callback; tx.fee.asset_id.arg = &tmp_ctx.signing_context.ui.fee_asset; - + // create stream for parsing pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, total_buffer_size); + //decoding tx message status = pb_decode(&stream, waves_Transaction_fields, &tx); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); @@ -303,6 +310,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); unsigned char tx_type = tmp_ctx.signing_context.data_type; + //prepeare non callback data for viewing depend on tx type if (tx_type == 3) { make_issue_ui(&tx); } else if (tx_type == 4) { @@ -318,6 +326,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, } else if (tx_type == 16) { make_invoke_ui(&tx); } + //finish parsing and view data tmp_ctx.signing_context.step = 7; tmp_ctx.signing_context.ui.finished = true; } diff --git a/src/ui/ui.c b/src/ui/ui.c index b97a4590..96c5cb1b 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -158,7 +158,7 @@ void build_other_data_ui() { void make_allowed_ui_steps(bool is_last) { uint32_t start_index; PRINTF("make_allowed_ui_steps start\n"); - if (tmp_ctx.signing_context.data_version > 2) { + if (tmp_ctx.signing_context.data_version > 2) { // if protobuf if (tmp_ctx.signing_context.ui.finished != true) { build_protobuf_ui( &tmp_ctx.signing_context.ui.proto, From 89ed48f015b552470120a0f2d0ebef083334b6ac Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Fri, 26 Jun 2020 15:38:12 +0400 Subject: [PATCH 14/26] comment printf for testing on blue --- src/main.c | 18 ++++-------------- src/nanopb/pb_custom.c | 8 ++++---- src/ui/transactions/protobuf.c | 2 +- src/ui/transactions/transfer.c | 2 +- src/ui/ui.c | 4 ++-- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/main.c b/src/main.c index 627ef7eb..c281f7f2 100644 --- a/src/main.c +++ b/src/main.c @@ -46,16 +46,6 @@ unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; extern void _ebss; -// Return true if there is less than MIN_BSS_STACK_GAP bytes available in the -// stack -void check_stack_overflow(int step) { - uint32_t stack_top = 0; - // PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: - // %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - - // ((uintptr_t)&_ebss)); - PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); -} - unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: @@ -193,7 +183,7 @@ uint32_t set_result_sign() { os_memmove((char *)G_io_apdu_buffer, tmp_ctx.signing_context.signature, sizeof(tmp_ctx.signing_context.signature)); - PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); + //PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); init_context(); @@ -246,7 +236,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, if (tmp_ctx.signing_context.step > 0) { tmp_ctx.signing_context.chunk += 1; } else { - PRINTF("make_sign_steps start\n"); + //PRINTF("make_sign_steps start\n"); show_processing(); tmp_ctx.signing_context.step = 1; tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; @@ -257,7 +247,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, stream_eddsa_sign_step5(&tmp_ctx.signing_context.eddsa_context, tmp_ctx.signing_context.signature); tmp_ctx.signing_context.step = 6; - PRINTF("make_sign_steps end\n"); + //PRINTF("make_sign_steps end\n"); os_memset(&tmp_ctx.signing_context.ui, 0, sizeof(tmp_ctx.signing_context.ui)); cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); @@ -381,7 +371,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } G_io_apdu_buffer[*tx] = sw >> 8; G_io_apdu_buffer[*tx + 1] = sw; - PRINTF("SW:\n%.*H\n", 2, G_io_apdu_buffer + *tx); + //PRINTF("SW:\n%.*H\n", 2, G_io_apdu_buffer + *tx); *tx += 2; } FINALLY {} diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index b56874d9..fe36422a 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -16,7 +16,7 @@ #define ERR_WRONG_MESSAGE_SIZE 0x6006 #define ERR_WRONG_PARAMETER 0x6007 -#define PRINTF_PB(...) // PRINTF(__VA_ARGS__) +//#define PRINTF_PB(...) // PRINTF(__VA_ARGS__) #if !defined(__GNUC__) || (__GNUC__ < 3) || \ (__GNUC__ == 3 && __GNUC_MINOR__ < 4) @@ -46,7 +46,7 @@ void fetch_new_apdu(uiProtobuf_t *state) { if (G_io_apdu_buffer[2] != P1_MORE && G_io_apdu_buffer[2] != P1_LAST) { THROW(SW_INCORRECT_P1_P2); } else if (state->bytes_stored + G_io_apdu_buffer[4] > sizeof(state->data)) { - PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, + //PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, G_io_apdu_buffer[4]); THROW(ERR_BUFFER_TOO_SMALL); } @@ -72,7 +72,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { bytes_not_read_yet = state->bytes_stored - state->read_offset; - PRINTF_PB("r: %d re: %d s %d\n", count, bytes_not_read_yet, + //PRINTF_PB("r: %d re: %d s %d\n", count, bytes_not_read_yet, state->bytes_stored); /* not enough data has been received and deciphered, we fetch a new apdu or @@ -84,7 +84,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { state->bytes_stored = bytes_not_read_yet; state->read_offset = 0; - PRINTF_PB("SHIFT LEFT: available: %d\n", bytes_not_read_yet); + //PRINTF_PB("SHIFT LEFT: available: %d\n", bytes_not_read_yet); // loop over apdu fetching while there's not enough bytes stored to feed the // amount requested diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 80af4f83..24c31302 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -303,7 +303,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, //decoding tx message status = pb_decode(&stream, waves_Transaction_fields, &tx); if (!status) { - PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + //PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } diff --git a/src/ui/transactions/transfer.c b/src/ui/transactions/transfer.c index b8b3011f..b602cd3e 100644 --- a/src/ui/transactions/transfer.c +++ b/src/ui/transactions/transfer.c @@ -83,7 +83,7 @@ void build_transfer_ui_step(bool is_last) { uint64_t amount = 0; uint64_t fee = 0; - PRINTF("build_ui_step step %d\n", tmp_ctx.signing_context.ui.byte.step); + //PRINTF("build_ui_step step %d\n", tmp_ctx.signing_context.ui.byte.step); switch (tmp_ctx.signing_context.ui.byte.step) { case 0: diff --git a/src/ui/ui.c b/src/ui/ui.c index 96c5cb1b..2e58383b 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -157,7 +157,7 @@ void build_other_data_ui() { void make_allowed_ui_steps(bool is_last) { uint32_t start_index; - PRINTF("make_allowed_ui_steps start\n"); + //PRINTF("make_allowed_ui_steps start\n"); if (tmp_ctx.signing_context.data_version > 2) { // if protobuf if (tmp_ctx.signing_context.ui.finished != true) { build_protobuf_ui( @@ -193,7 +193,7 @@ void make_allowed_ui_steps(bool is_last) { G_io_apdu_buffer[4] - start_index, NULL, 0); tmp_ctx.signing_context.ui.byte.chunk_used = 0; } - PRINTF("make_allowed_ui_steps end\n"); + //PRINTF("make_allowed_ui_steps end\n"); } // Show the transaction details for the user to approve From fe2c395d92961c6d70cda299bdfe899a8bbba147 Mon Sep 17 00:00:00 2001 From: Sergey Tolmachev Date: Fri, 26 Jun 2020 15:19:08 +0300 Subject: [PATCH 15/26] remove processing message from blue --- src/ui/blue/ui_menus_blue.h | 50 ------------------------------------- src/ui/ui.c | 3 ++- 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index 6272770c..c838634f 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -4486,52 +4486,6 @@ const bagl_element_t ui_address_blue[] = { NULL}, }; -const bagl_element_t ui_processing_blue[] = { - {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, - 0x000000, 0, 0}, - NULL, - 0, - 0, - 0, - NULL, - NULL, - NULL}, - - // erase screen (only under the status bar) - {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, - COLOR_APP, 0, 0}, - NULL, - 0, - 0, - 0, - NULL, - NULL, - NULL}, - - /// TOP STATUS BAR - {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, - BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, - "PROCESSING", - 0, - 0, - 0, - NULL, - NULL, - NULL}, - - {{BAGL_LABELINE, 0x00, 0, 270, 320, 30, 0, 0, BAGL_FILL, 0x000000, - COLOR_BG_1, - BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, - "Processing...", - 0, - 0, - 0, - NULL, - NULL, - NULL}, - -}; - unsigned int ui_idle_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; @@ -4625,9 +4579,5 @@ unsigned int ui_approval_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; } -unsigned int ui_processing_blue_button(unsigned int button_mask, - unsigned int button_mask_counter) { - return 0; -} #endif // #if defined(TARGET_BLUE) \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index 96c5cb1b..d903c229 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -329,7 +329,8 @@ void show_sign_protobuf_ui() { void show_processing() { #if defined(TARGET_BLUE) - UX_DISPLAY(ui_processing_blue, NULL); +// this freeze device after pb update +// UX_DISPLAY(ui_processing_blue, NULL); #else ux_flow_init(0, ux_processing_flow, NULL); #endif From 39fa9561581f442e493401e7342de1c0eabcf6e4 Mon Sep 17 00:00:00 2001 From: Sergey Tolmachev Date: Fri, 26 Jun 2020 15:23:05 +0300 Subject: [PATCH 16/26] Revert "comment printf for testing on blue" This reverts commit 89ed48f0 --- src/main.c | 18 ++++++++++++++---- src/nanopb/pb_custom.c | 8 ++++---- src/ui/transactions/protobuf.c | 2 +- src/ui/transactions/transfer.c | 2 +- src/ui/ui.c | 4 ++-- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index c281f7f2..627ef7eb 100644 --- a/src/main.c +++ b/src/main.c @@ -46,6 +46,16 @@ unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; extern void _ebss; +// Return true if there is less than MIN_BSS_STACK_GAP bytes available in the +// stack +void check_stack_overflow(int step) { + uint32_t stack_top = 0; + // PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: + // %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - + // ((uintptr_t)&_ebss)); + PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); +} + unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: @@ -183,7 +193,7 @@ uint32_t set_result_sign() { os_memmove((char *)G_io_apdu_buffer, tmp_ctx.signing_context.signature, sizeof(tmp_ctx.signing_context.signature)); - //PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); + PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); init_context(); @@ -236,7 +246,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, if (tmp_ctx.signing_context.step > 0) { tmp_ctx.signing_context.chunk += 1; } else { - //PRINTF("make_sign_steps start\n"); + PRINTF("make_sign_steps start\n"); show_processing(); tmp_ctx.signing_context.step = 1; tmp_ctx.signing_context.network_byte = G_io_apdu_buffer[3]; @@ -247,7 +257,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, stream_eddsa_sign_step5(&tmp_ctx.signing_context.eddsa_context, tmp_ctx.signing_context.signature); tmp_ctx.signing_context.step = 6; - //PRINTF("make_sign_steps end\n"); + PRINTF("make_sign_steps end\n"); os_memset(&tmp_ctx.signing_context.ui, 0, sizeof(tmp_ctx.signing_context.ui)); cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); @@ -371,7 +381,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } G_io_apdu_buffer[*tx] = sw >> 8; G_io_apdu_buffer[*tx + 1] = sw; - //PRINTF("SW:\n%.*H\n", 2, G_io_apdu_buffer + *tx); + PRINTF("SW:\n%.*H\n", 2, G_io_apdu_buffer + *tx); *tx += 2; } FINALLY {} diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index fe36422a..b56874d9 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -16,7 +16,7 @@ #define ERR_WRONG_MESSAGE_SIZE 0x6006 #define ERR_WRONG_PARAMETER 0x6007 -//#define PRINTF_PB(...) // PRINTF(__VA_ARGS__) +#define PRINTF_PB(...) // PRINTF(__VA_ARGS__) #if !defined(__GNUC__) || (__GNUC__ < 3) || \ (__GNUC__ == 3 && __GNUC_MINOR__ < 4) @@ -46,7 +46,7 @@ void fetch_new_apdu(uiProtobuf_t *state) { if (G_io_apdu_buffer[2] != P1_MORE && G_io_apdu_buffer[2] != P1_LAST) { THROW(SW_INCORRECT_P1_P2); } else if (state->bytes_stored + G_io_apdu_buffer[4] > sizeof(state->data)) { - //PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, + PRINTF("ERR_BUFF_TOO_SMALL: %d %d\n", state->bytes_stored, G_io_apdu_buffer[4]); THROW(ERR_BUFFER_TOO_SMALL); } @@ -72,7 +72,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { bytes_not_read_yet = state->bytes_stored - state->read_offset; - //PRINTF_PB("r: %d re: %d s %d\n", count, bytes_not_read_yet, + PRINTF_PB("r: %d re: %d s %d\n", count, bytes_not_read_yet, state->bytes_stored); /* not enough data has been received and deciphered, we fetch a new apdu or @@ -84,7 +84,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { state->bytes_stored = bytes_not_read_yet; state->read_offset = 0; - //PRINTF_PB("SHIFT LEFT: available: %d\n", bytes_not_read_yet); + PRINTF_PB("SHIFT LEFT: available: %d\n", bytes_not_read_yet); // loop over apdu fetching while there's not enough bytes stored to feed the // amount requested diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 24c31302..80af4f83 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -303,7 +303,7 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, //decoding tx message status = pb_decode(&stream, waves_Transaction_fields, &tx); if (!status) { - //PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } diff --git a/src/ui/transactions/transfer.c b/src/ui/transactions/transfer.c index b602cd3e..b8b3011f 100644 --- a/src/ui/transactions/transfer.c +++ b/src/ui/transactions/transfer.c @@ -83,7 +83,7 @@ void build_transfer_ui_step(bool is_last) { uint64_t amount = 0; uint64_t fee = 0; - //PRINTF("build_ui_step step %d\n", tmp_ctx.signing_context.ui.byte.step); + PRINTF("build_ui_step step %d\n", tmp_ctx.signing_context.ui.byte.step); switch (tmp_ctx.signing_context.ui.byte.step) { case 0: diff --git a/src/ui/ui.c b/src/ui/ui.c index c17f7eec..d903c229 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -157,7 +157,7 @@ void build_other_data_ui() { void make_allowed_ui_steps(bool is_last) { uint32_t start_index; - //PRINTF("make_allowed_ui_steps start\n"); + PRINTF("make_allowed_ui_steps start\n"); if (tmp_ctx.signing_context.data_version > 2) { // if protobuf if (tmp_ctx.signing_context.ui.finished != true) { build_protobuf_ui( @@ -193,7 +193,7 @@ void make_allowed_ui_steps(bool is_last) { G_io_apdu_buffer[4] - start_index, NULL, 0); tmp_ctx.signing_context.ui.byte.chunk_used = 0; } - //PRINTF("make_allowed_ui_steps end\n"); + PRINTF("make_allowed_ui_steps end\n"); } // Show the transaction details for the user to approve From 8316aabff2b955d298335bba02b2ae717f644738 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Fri, 26 Jun 2020 18:49:35 +0400 Subject: [PATCH 17/26] add order ui for protobuf --- python/ledger-waves.py | 510 +++++++++++++++++++++------------ src/main.c | 26 +- src/main.h | 3 +- src/nanopb/pb_custom.c | 2 +- src/ui/blue/ui_menus_blue.h | 341 +++++++++++++++++++++- src/ui/nanox/ui_menus_nanox.h | 71 ++++- src/ui/transactions/protobuf.c | 107 +++++-- src/ui/transactions/protobuf.h | 1 + src/ui/ui.c | 7 + 9 files changed, 826 insertions(+), 242 deletions(-) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index cd5b71bf..b7c4b808 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -24,6 +24,7 @@ import pywaves as pw import time import base64 +import order_pb2 as opb from amount_pb2 import Amount import transaction_pb2 as tpb from recipient_pb2 import Recipient @@ -36,6 +37,7 @@ # 'T' for testnet, 'W' for mainnet chain_id = 'W' + class colors: '''Colors class: reset all colors with colors.reset @@ -86,14 +88,16 @@ def getKeysFromDongle(path, networkByte): global dongle while (True): try: - data_bytes = bytes(("800400" + '{0:x}'.format(ord(networkByte)) + "14").decode('hex')) + path_to_bytes(path) + data_bytes = bytes( + ("800400" + '{0:x}'.format(ord(networkByte)) + "14").decode('hex')) + path_to_bytes(path) data = dongle.exchange(data_bytes) return [data[0:32], data[32:67]] except CommException as e: if (e.sw == 0x6985): print(colors.fg.red + "Required condition failed." + colors.reset) if (e.sw == 0x9100): - print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + print( + colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) break except Exception as e: raw_input( @@ -101,6 +105,7 @@ def getKeysFromDongle(path, networkByte): sys.exc_clear() break + def getVersionFromDongle(): global dongle while (True): @@ -112,7 +117,8 @@ def getVersionFromDongle(): if (e.sw == 0x6985): print(colors.fg.red + "Required condition failed." + colors.reset) if (e.sw == 0x9100): - print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + print( + colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) break except Exception as e: raw_input( @@ -120,6 +126,7 @@ def getVersionFromDongle(): sys.exc_clear() break + # 128 - 5 service bytes CHUNK_SIZE = 123 PRIME_DERIVATION_FLAG = 0x80000000 @@ -165,7 +172,7 @@ def expand_path(n): return path -def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = b'\2'): +def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version=b'\2'): if timestamp == 0: timestamp = int(time.time() * 1000) @@ -173,7 +180,7 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee if version == b'\2': sData += version - + start_index = 31 start_len = len(sData) + start_index @@ -181,7 +188,7 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee sData += field end_len = start_len + len(field) print('public key [{} - {}]'.format(start_len, end_len)) - + start_len = len(sData) + start_index field = (b'\1' + base58.b58decode(asset.assetId) if asset else b'\0') sData += field @@ -232,140 +239,211 @@ def build_transfer_bytes(publicKey, recipient, asset, amount, attachment='', fee return sData -def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) to = Recipient(public_key_hash=base58.b58decode(recipient)) - amountTx= Amount(asset_id=(base58.b58decode(asset.assetId) if asset else b'\0'), amount=amount) - transfer = tpb.TransferTransactionData(recipient=to, amount=amountTx, attachment=attachment) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) + amountTx = Amount(asset_id=(base58.b58decode( + asset.assetId) if asset else b'\0'), amount=amount) + transfer = tpb.TransferTransactionData( + recipient=to, amount=amountTx, attachment=attachment) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) return trx.SerializeToString() -def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) to = Recipient(public_key_hash=base58.b58decode(recipient)) transfers = list() - transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) - transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) - transfers.append(tpb.MassTransferTransactionData.Transfer(recipient=to, amount=amount)) - mass_transfer = tpb.MassTransferTransactionData(asset_id=(base58.b58decode(asset.assetId) if asset else b'\0'), transfers = transfers, attachment=attachment) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, mass_transfer=mass_transfer) + transfers.append(tpb.MassTransferTransactionData.Transfer( + recipient=to, amount=amount)) + transfers.append(tpb.MassTransferTransactionData.Transfer( + recipient=to, amount=amount)) + transfers.append(tpb.MassTransferTransactionData.Transfer( + recipient=to, amount=amount)) + mass_transfer = tpb.MassTransferTransactionData(asset_id=(base58.b58decode( + asset.assetId) if asset else b'\0'), transfers=transfers, attachment=attachment) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, mass_transfer=mass_transfer) return trx.SerializeToString() -def build_issue_protobuf(publicKey, name, descr, amount, decimals, reissue, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_issue_protobuf(publicKey, name, descr, amount, decimals, reissue, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - issue = tpb.IssueTransactionData(name = name, description = descr, amount=amount, decimals=decimals, reissuable = reissue) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, issue=issue) + issue = tpb.IssueTransactionData( + name=name, description=descr, amount=amount, decimals=decimals, reissuable=reissue) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, issue=issue) return trx.SerializeToString() -def build_set_ac_script_protobuf(publicKey, script, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_set_ac_script_protobuf(publicKey, script, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) scr = tpb.SetScriptTransactionData(script=script) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, set_script=scr) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, set_script=scr) return trx.SerializeToString() -def build_set_as_script_protobuf(publicKey, asset, script, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_set_as_script_protobuf(publicKey, asset, script, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - scr = tpb.SetAssetScriptTransactionData(asset_id=base58.b58decode(asset.assetId), script=script) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, set_asset_script=scr) + scr = tpb.SetAssetScriptTransactionData( + asset_id=base58.b58decode(asset.assetId), script=script) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, set_asset_script=scr) return trx.SerializeToString() -def build_reissue_protobuf(publicKey, asset, amount, re, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_reissue_protobuf(publicKey, asset, amount, re, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) - reissue = tpb.ReissueTransactionData(asset_amount=amountTx, reissuable = re) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, reissue=reissue) + amountTx = Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + reissue = tpb.ReissueTransactionData(asset_amount=amountTx, reissuable=re) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, reissue=reissue) return trx.SerializeToString() -def build_burn_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_burn_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + amountTx = Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) burn = tpb.BurnTransactionData(asset_amount=amountTx) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, burn=burn) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, burn=burn) return trx.SerializeToString() -def build_lease_protobuf(publicKey, to, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_lease_protobuf(publicKey, to, amount, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) recipient = Recipient(public_key_hash=base58.b58decode(to)) lease = tpb.LeaseTransactionData(recipient=recipient, amount=amount) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, lease=lease) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, lease=lease) return trx.SerializeToString() -def build_cancel_lease_protobuf(publicKey, leaseId, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_cancel_lease_protobuf(publicKey, leaseId, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - lease_cancel = tpb.LeaseCancelTransactionData(lease_id = base58.b58decode(leaseId)) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, lease_cancel=lease_cancel) + lease_cancel = tpb.LeaseCancelTransactionData( + lease_id=base58.b58decode(leaseId)) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, lease_cancel=lease_cancel) return trx.SerializeToString() -def build_creating_alias_protobuf(publicKey, alias, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_creating_alias_protobuf(publicKey, alias, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - alias = tpb.CreateAliasTransactionData(alias = alias) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, create_alias=alias) + alias = tpb.CreateAliasTransactionData(alias=alias) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, create_alias=alias) return trx.SerializeToString() -def build_update_asset_protobuf(publicKey, asset, name, description, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_update_asset_protobuf(publicKey, asset, name, description, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - update_asset = tpb.UpdateAssetInfoTransactionData(asset_id = base58.b58decode(asset.assetId), name=name, description=description) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, update_asset_info=update_asset) + update_asset = tpb.UpdateAssetInfoTransactionData( + asset_id=base58.b58decode(asset.assetId), name=name, description=description) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, update_asset_info=update_asset) return trx.SerializeToString() -def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) list = [] for x in range(1): k = "j" + str(x) - s = "jjjjjjj" + str(x) - dataEntery = tpb.DataTransactionData.DataEntry(key=k, string_value=s ) + s = "jjjjjjj" + str(x) + dataEntery = tpb.DataTransactionData.DataEntry(key=k, string_value=s) list.append(dataEntery) - data = tpb.DataTransactionData(data = list) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b''), amount=txFee) - trx = tpb.Transaction(chain_id=84, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, data_transaction=data) + data = tpb.DataTransactionData(data=list) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b''), amount=txFee) + trx = tpb.Transaction(chain_id=84, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, data_transaction=data) return trx.SerializeToString() -def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) - amountTx= Amount(asset_id=(base58.b58decode(asset.assetId) if feeAsset else b'\0'), amount=amount) + amountTx = Amount(asset_id=(base58.b58decode(asset.assetId) + if feeAsset else b'\0'), amount=amount) sponsorship = tpb.SponsorFeeTransactionData(min_fee=amountTx) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, sponsor_fee=sponsorship) - return trx.SerializeToString() + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, sponsor_fee=sponsorship) + return trx.SerializeToString() -def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amount2, feeAsset='', txFee=100000, timestamp=0, version = 3): + +def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amount2, feeAsset='', txFee=100000, timestamp=0, version=3): if timestamp == 0: timestamp = int(time.time() * 1000) amounts = [] - amountTx= Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) + amountTx = Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) amounts.append(amountTx) - amountTx= Amount(asset_id=base58.b58decode(asset2.assetId), amount=amount2) + amountTx = Amount(asset_id=base58.b58decode( + asset2.assetId), amount=amount2) amounts.append(amountTx) to = Recipient(public_key_hash=base58.b58decode(dapp)) - invoke = tpb.InvokeScriptTransactionData(d_app = to, function_call = function, payments = amounts) - fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, invoke_script=invoke) - return trx.SerializeToString() + invoke = tpb.InvokeScriptTransactionData( + d_app=to, function_call=function, payments=amounts) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + publicKey), fee=fee, timestamp=timestamp, version=version, invoke_script=invoke) + return trx.SerializeToString() + + +def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, amount, price, expiration, timestamp=0, feeAsset='', txFee=100000, version=3): + if timestamp == 0: + timestamp = int(time.time() * 1000) + fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) + if feeAsset else b'\0'), amount=txFee) + assetPair = opb.AssetPair( + amount_asset_id=(base58.b58decode(amountAsset.assetId) + if amountAsset else b'\0'), + price_asset_id=(base58.b58decode(priceAsset.assetId) + if priceAsset else b'\0'), + ) + order = opb.Order(chain_id=87, sender_public_key=base58.b58decode(publicKey), matcher_public_key=base58.b58decode( + matcherPK), asset_pair=assetPair, order_side=1, amount=amount, price=price, timestamp=timestamp, expiration=expiration, matcher_fee=fee, version=3) + return order.SerializeToString() while (True): while (dongle == None): @@ -379,8 +457,10 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou sys.exc_clear() print("") - print(colors.fg.lightcyan + colors.bold + "Ledger Nano S - Waves test app" + colors.reset) - print(colors.fg.white + "\t 1. Get PublicKey/Address from Ledger Nano S" + colors.reset) + print(colors.fg.lightcyan + colors.bold + + "Ledger Nano S - Waves test app" + colors.reset) + print(colors.fg.white + + "\t 1. Get PublicKey/Address from Ledger Nano S" + colors.reset) print(colors.fg.white + "\t 2. Sign tx using Ledger Nano S" + colors.reset) print(colors.fg.white + "\t 3. Get app version from Ledger Nano S" + colors.reset) print(colors.fg.white + "\t 4. Sign protobuf tx using Ledger Nano S" + colors.reset) @@ -397,7 +477,8 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou publicKey = keys[0] address = keys[1] - print(colors.fg.blue + "publicKey (base58): " + colors.reset + base58.b58encode(str(publicKey))) + print(colors.fg.blue + "publicKey (base58): " + + colors.reset + base58.b58encode(str(publicKey))) print(colors.fg.blue + "address: " + colors.reset + address) elif (select == "2"): path = raw_input( @@ -405,7 +486,8 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou if len(path) == 0: path = "44'/5741564'/0'/0'/1'" binary_data = path_to_bytes(expand_path(path)) - print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) + print(colors.fg.lightgrey + "path bytes: " + + base58.b58encode(str(path_to_bytes(expand_path(path))))) # tx amount asset decimals binary_data += chr(8) @@ -423,9 +505,11 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou # fee: 0.001 # fee asset: WAVES some_transfer_bytes = build_transfer_bytes('4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', - pw.Address('3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000000, - 'privet', timestamp = 1526477921829) + pw.Address( + '3PMpANFyKGBwzvv1UVk2KdN23fJZ8sXSVEK'), + pw.Asset( + '9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000000, + 'privet', timestamp=1526477921829) input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: @@ -435,15 +519,18 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou binary_data += some_transfer_bytes binary_data += some_transfer_bytes binary_data += some_transfer_bytes - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) + print(colors.fg.lightgrey + "tx bytes: " + + base58.b58encode(str(some_transfer_bytes))) else: binary_input = base58.b58decode(input) binary_data += struct.pack(">I", len(binary_input)) binary_data += binary_input binary_data += binary_input binary_data += binary_input - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) - print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) + print(colors.fg.lightgrey + "tx bytes: " + + base58.b58encode(str(binary_input))) + print(colors.fg.lightgrey + "all request bytes: " + + base58.b58encode(str(binary_data))) signature = None while (True): try: @@ -461,18 +548,22 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou if (offset == 0): print("Waiting for approval to sign on the Ledger Nano S") - apdu = bytes("8002".decode('hex')) + chr(p1) + chain_id + chr(len(chunk)) + bytes(chunk) + apdu = bytes("8002".decode('hex')) + chr(p1) + \ + chain_id + chr(len(chunk)) + bytes(chunk) signature = dongle.exchange(apdu) offset += len(chunk) print("signature " + base58.b58encode(str(signature))) break except CommException as e: if (e.sw == 0x6990): - print(colors.fg.red + "Transaction buffer max size reached." + colors.reset) + print(colors.fg.red + + "Transaction buffer max size reached." + colors.reset) if (e.sw == 0x6985): - print(colors.fg.red + "Required condition failed." + colors.reset) + print(colors.fg.red + + "Required condition failed." + colors.reset) if (e.sw == 0x9100): - print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + print( + colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) break except Exception as e: print(e, type(e)) @@ -483,12 +574,15 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou sys.exc_clear() elif (select == "3"): version = getVersionFromDongle() - print('App version is {}.{}.{}'.format(version[0],version[1],version[2])) + print('App version is {}.{}.{}'.format( + version[0], version[1], version[2])) elif (select == "4"): while (True): print("") - print(colors.fg.lightcyan + colors.bold + "Ledger Nano S - Waves test app" + colors.reset) - print(colors.fg.lightcyan + colors.bold + "Test protobuf transactions" + colors.reset) + print(colors.fg.lightcyan + colors.bold + + "Ledger Nano S - Waves test app" + colors.reset) + print(colors.fg.lightcyan + colors.bold + + "Test protobuf transactions" + colors.reset) print(colors.fg.white + "\t 3. Issue" + colors.reset) print(colors.fg.white + "\t 4. Transfer" + colors.reset) print(colors.fg.white + "\t 5. Reissue" + colors.reset) @@ -504,179 +598,215 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou print(colors.fg.white + "\t 15. Set Asset Script" + colors.reset) print(colors.fg.white + "\t 16. Invoke Script" + colors.reset) print(colors.fg.white + "\t 17. Update Asset Info" + colors.reset) + print(colors.fg.white + "\t 252. Order" + colors.reset) print(colors.fg.white + "\t 0. Exit" + colors.reset) - select = raw_input(colors.fg.cyan + "Please select transaction type> " + colors.reset) - decimals = 8 # tx amount asset decimals + select = raw_input( + colors.fg.cyan + "Please select transaction type> " + colors.reset) + decimals = 8 # tx amount asset decimals decimals2 = 0 - feeDecimals = 8 #fee amount asset decimals + feeDecimals = 8 # fee amount asset decimals if (select == "3"): decimals = 3 some_transfer_bytes = build_issue_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "Test asset name", - "Test asset description, Test asset description, Test asset description", - 1000000000, - decimals, - True, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + "Test asset name", + "Test asset description, Test asset description, Test asset description", + 1000000000, + decimals, + True, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "4"): decimals = 8 some_transfer_bytes = build_transfer_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL - pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), - 100000000, - 'privet', - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + "23edvPK94JRdmDj7rKwzLbu22Sem", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), + 100000000, + 'privet', + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "5"): decimals = 8 some_transfer_bytes = build_reissue_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), - 100000000, + 100000000, True, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 - ) + ) elif (select == "6"): decimals = 8 some_transfer_bytes = build_burn_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), 1000000000, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) - #elif (select == "7"): - + # elif (select == "7"): + elif (select == "8"): some_transfer_bytes = build_lease_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + "23edvPK94JRdmDj7rKwzLbu22Sem", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL 100000000000, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "9"): some_transfer_bytes = build_cancel_lease_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', 'B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu', - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "10"): some_transfer_bytes = build_creating_alias_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', "Test Alias", - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "11"): some_transfer_bytes = build_masstransfer_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + "23edvPK94JRdmDj7rKwzLbu22Sem", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), 10000000, 'privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000privet0000', pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + 100000, + 1526477921829, 3 ) elif (select == "12"): some_transfer_bytes = build_data_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "13"): script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") - some_transfer_bytes = build_set_ac_script_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + some_transfer_bytes = build_set_ac_script_protobuf( + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', script, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 - ) + ) elif (select == "14"): decimals = 6 some_transfer_bytes = build_sponsorship_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), 10000, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 ) elif (select == "15"): script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") - some_transfer_bytes = build_set_as_script_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + some_transfer_bytes = build_set_as_script_protobuf( + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), script, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, 3 - ) + ) elif (select == "16"): fname = "function_name" - function_call = chr(2) + chr(2) + "argument1".encode() + chr(2) + "argument2".encode() - fcal=chr(1) + chr(9) + chr(1) + struct.pack(">I", len(fname)) + fname.encode() + function_call + function_call = chr( + 2) + chr(2) + "argument1".encode() + chr(2) + "argument2".encode() + fcal = chr(1) + chr(9) + chr(1) + struct.pack(">I", + len(fname)) + fname.encode() + function_call decimals = 6 decimals2 = 8 some_transfer_bytes = build_invoke_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - "23edvPK94JRdmDj7rKwzLbu22Sem", #3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + "23edvPK94JRdmDj7rKwzLbu22Sem", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL fcal, pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), 1000000, - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 1000000000, + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 1000000000, ) - some_transfer_bytes = base58.b58decode("FgBL1ir521wY8kGhSGQF3Tdxx6UtF46W15hoTCccswWjTRpnM8JE48R8LJZcerjGVNFNwc8W2vY67Uhb6wfH8BHFb5iMzUKAg72MWSriBZo6FGu2YgQaq4JNd4TbteB4ddNMXu7Gi8XMGvH6vLiy4EJWVXHCZWmjow6iJydGi56h6xHriwhmSbxyB81Tad6dUHwsojK7287yrhHpZbH4QMB5ScCuq5HHd4SjSsuMaGY422V12baZFu48NCi5obPEri5JiLzXz51BEuQTQx3gKtikhc92VbpjgHCfEjfxx7gcP2XT5ydTaWR2hYe2Jv9sQzSSbhvfj3Av62rJS9uj5rS1DeAJkJbBWGWzVehqfpRWev7aDwvqtnhzCygSrAGKQoR6k9dCaaRzVJo8Tk1f4gBsdqgwLUofvNTC4nJpzawR8pujoaKVfZwQLYJjsA69dUwhexQXtmEWQjdtsajLbtbakFbEdrcDWgYckvGDYeyyUAinN1Unb9iGJMNGvWDyKiQiCT7WDmgMzCE623xEfrTgEXx45NuuNpGdALcfBi7Fm6JtzGoPhJ7ftsCFMxXvyhBwDUq59L3wBzaXGw4ikNwBrQsFTzmMVCzU2Dixnm9nyuZKoipuqW4B2CwnQGJgrAqhy8CkMtAyZsW1U4AwrZhVQiKVDX8M8P5uYJ2dnCmjSazJnp4k1YSuwm7mFBbcYfqsxVcB6TUUzfqdb4ADh3ULrQacKWdpMGPA3Xnj2kJMuA3GNbwosh7okvRZWaxTjujDx4jkmh2uZtbqMn4BNxdqWqknnLpMupbhU95oUdbxvSxXiLnRQEgmWjkLoavmw5EJQVS7ck3yfkZTkArkPSJZNJo4E9smVgpks1eaUNfKvZkGQuDU2kYqPSgmQ8uLtN1VugeEydaCUFUQWeTbDR2iiWKpCzyTVFmkWi7G5Hg8shUF88DioFZsCGeJooRG5DNa2qvYJ53o2z4owVuxw1K6L3mU8RxY5kcvagoK3PvudxYPvNExKU7iEedLT9dgTgtJ431foD1kLuTDV93wWGm3oiFVW7gvHM9zZdeyqBRF39aQwi1MX3a4nasFdf3RnX1WSAhD6tYA44jNWZ95Cw675UT1SWJb688TpPppiH6eiL8e6uEEevCGKw3zPJ5Vmb325PcotS3BZetZ2fEwfRrW4xcZvRUYkD3uS1yGExpcU8uJNvYybb7padUuU6udtrdoZerxLwjzcfp3gZGUUGwo8C7X9ZRWkCP22jc4d9osKqfvJQQzgnbjJpRvdhM3RZ3gd5CQ9gaVrDkT1ffi9qUeKvUrw18k2Y22NmjfQYKx9b9DfZBye4sYEte4TfFyJmPTEd5RZkwDh9vhzSjx4S3WkfYAzbeETvzap1HsfJC1zKLC5cKnkJPBRei4QAZCMsQo3oqCVFAwFkrKbxhJQAbkaxtEnQs4pG3NqWFMKskYNQjjkuBf1EL9q1X4iM6Jr8ocSjxpXC9NLSyiP4DjCZxhNyWERZvFXmmTgjycpkYzyzGbVtwuLvSBpnPHZysKmHnaPvMiHz9rfrVG9187kdk8RURjH1PsPckJLKPE2ApFz6Qi3Gq5bTWwiij6Hi9eEVUwUWERAZon1PBniWk2cLHAoZpTpViKQWhcR8fWaTLKUVFiMDM6ofserGp9wgabXZAY3vw7daYVEwYzHmsZovgXAnVZCAzUeZaJ7PD8EscWy58ym3dh2NkE33aT5AfZsPFwk9wDU8QA4uut6cDFWd5Ua"); - + elif (select == "17"): some_transfer_bytes = build_update_asset_protobuf( - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', #3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), "Test name 1", - "Test descr", - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, + "Test descr", + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 100000, + 1526477921829, + 3 + ) + elif(select == "252"): + some_transfer_bytes = build_order_protobuf( + # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt + '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', + # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + "8f9MUt5QXBBC11Yu4LcfWSdgdUSZBbvXATDfykQymmLe", + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), + 1, # sell + 1000000, + 100, + 1526477921829, + 1526477921829, + '', # waves + 100000, 3 - ) + ) else: - break; - - path = raw_input(colors.fg.lightblue + "Please input BIP-32 path (for example \"44'/5741564'/0'/0'/1'\")> " + colors.reset) + break + + path = raw_input( + colors.fg.lightblue + "Please input BIP-32 path (for example \"44'/5741564'/0'/0'/1'\")> " + colors.reset) if len(path) == 0: path = "44'/5741564'/0'/0'/1'" binary_data = path_to_bytes(expand_path(path)) - print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) + print(colors.fg.lightgrey + "path bytes: " + + base58.b58encode(str(path_to_bytes(expand_path(path))))) # tx amount asset decimals binary_data += chr(decimals) @@ -688,7 +818,7 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou #some_transfer_bytes = base58.b58decode("uq4YDsWuUhQ2ajpzvHxWeikWkF8XodVWi8F1VdYsqFESLGc2k6g5UvtxVrER4a") #some_transfer_bytes = base58.b58decode("c4wP1kugNdzm3Sm88YVaJ3dVZ73S1RshSZNxvqmCZbQUW5yDSCGuXVK666EwipM4yqoA7EeDzseLjSDRQFaoG7pcGvSMrHEqVxw8z3qoBb3zjEvpMhFG598koLXBTZS8RXvN4U4LLJpUcEnqAbDrM4jeUwcYkqekMM3Mbm8tWAaTUbwHgE4DbUPoUid3xncWovvcZ5j9RBExrKpNhxmN1YDS2mwK59GnN4KxUxMnwAuQ5dgrbkAnDGCV9TjeJemj6eCLHKr6mhGUns7W69fRioUmJMADbkYTvgJe1nFgG5n8GiavNfDeCNKD8CYjwZBgZtRZma88pcfAtgBG293JTgcBgSdJWAMTT5J4B5URhrJWyF3mNdq6rbumTGWTGpA8HgYEPA2VgD6EGRprm1DYwdr8UD7HEx2gzDTV6A31") input = raw_input(colors.fg.lightblue + "Please input message to sign (for example \"" + base58.b58encode( - str(some_transfer_bytes)) + "\")> " + colors.reset) + str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: # 2 first bytes aren't the tx data, but info type for the ledger binary_data += chr(int(select)) + chr(3) @@ -696,16 +826,19 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou binary_data += some_transfer_bytes binary_data += some_transfer_bytes binary_data += some_transfer_bytes - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) + print(colors.fg.lightgrey + "tx bytes: " + + base58.b58encode(str(some_transfer_bytes))) else: binary_input = base58.b58decode(input) binary_data += struct.pack(">I", len(binary_input)) binary_data += binary_input binary_data += binary_input binary_data += binary_input - print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) - print(colors.fg.lightgrey + "all request bytes: " + base58.b58encode(str(binary_data))) - + print(colors.fg.lightgrey + "tx bytes: " + + base58.b58encode(str(binary_input))) + print(colors.fg.lightgrey + "all request bytes: " + + base58.b58encode(str(binary_data))) + signature = None while (True): try: @@ -721,21 +854,26 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou p1 = 0x00 if (offset == 0): - print("Waiting for approval to sign on the Ledger Nano S") + print( + "Waiting for approval to sign on the Ledger Nano S") - apdu = bytes("8002".decode('hex')) + chr(p1) + chain_id + chr(len(chunk)) + bytes(chunk) + apdu = bytes("8002".decode('hex')) + chr(p1) + \ + chain_id + chr(len(chunk)) + bytes(chunk) signature = dongle.exchange(apdu) offset += len(chunk) - + print("signature " + base58.b58encode(str(signature))) break except CommException as e: if (e.sw == 0x6990): - print(colors.fg.red + "Transaction buffer max size reached." + colors.reset) + print( + colors.fg.red + "Transaction buffer max size reached." + colors.reset) if (e.sw == 0x6985): - print(colors.fg.red + "Required condition failed." + colors.reset) + print(colors.fg.red + + "Required condition failed." + colors.reset) if (e.sw == 0x9100): - print(colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) + print( + colors.fg.red + "User denied signing request on Ledger Nano S device." + colors.reset) break except Exception as e: print(e, type(e)) diff --git a/src/main.c b/src/main.c index 627ef7eb..46684721 100644 --- a/src/main.c +++ b/src/main.c @@ -44,18 +44,6 @@ unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; #error This application only supports the Ledger Nano S, Nano X and the Ledger Blue #endif -extern void _ebss; - -// Return true if there is less than MIN_BSS_STACK_GAP bytes available in the -// stack -void check_stack_overflow(int step) { - uint32_t stack_top = 0; - // PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: - // %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - - // ((uintptr_t)&_ebss)); - PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); -} - unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: @@ -274,8 +262,9 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } else { make_allowed_ui_steps(false); } - - if (tmp_ctx.signing_context.step == 7) { // all data parsed and prepeared to view + + if (tmp_ctx.signing_context.step == + 7) { // all data parsed and prepeared to view unsigned char third_data_hash[64]; cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, third_data_hash, 32); @@ -294,7 +283,8 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.from); - // if transaction has from field and it is pubkey hash will convert to address + // if transaction has from field and it is pubkey hash will convert to + // address if (tmp_ctx.signing_context.ui.pkhash) { waves_public_key_hash_to_address( tmp_ctx.signing_context.ui.line3, @@ -302,6 +292,12 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.ui.line3); } if (tmp_ctx.signing_context.data_version > 2) { + if (tmp_ctx.signing_context.data_type == 252) { + // convert matcher public key to address + waves_public_key_to_address(tmp_ctx.signing_context.ui.line2, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line2); + } show_sign_protobuf_ui(); } else { show_sign_ui(); diff --git a/src/main.h b/src/main.h index aa1e6787..5c4ed49f 100644 --- a/src/main.h +++ b/src/main.h @@ -95,7 +95,8 @@ typedef struct uiContext_t { unsigned char fee_asset[45]; unsigned char line1[45]; unsigned char line2[45]; - unsigned char line3[45]; // reserved for recipient if transaction has resipient message + unsigned char + line3[45]; // reserved for recipient if transaction has resipient message unsigned char line4[45]; unsigned char line5[45]; unsigned char line6[20]; diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index b56874d9..d357ab7e 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -101,7 +101,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { } // fetch next bytes fetch_new_apdu(state); - //creating hash to check view and sign data are the same + // creating hash to check view and sign data are the same cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, G_io_apdu_buffer + 5, G_io_apdu_buffer[4], NULL, 0); os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index c838634f..0209ac71 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -4012,7 +4012,7 @@ const bagl_element_t ui_verify_invoke_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, "Payment 1 asset", 0, @@ -4043,7 +4043,7 @@ const bagl_element_t ui_verify_invoke_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, "Payment 2 amount", 0, @@ -4074,7 +4074,7 @@ const bagl_element_t ui_verify_invoke_blue[] = { NULL, NULL}, - {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, "Payment 2 asset", 0, @@ -4256,6 +4256,8 @@ const bagl_element_t ui_verify_invoke_blue[] = { }; +////////////////////////////////////////////////////////////////////////////// + const bagl_element_t ui_approval_blue[] = { {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, 0x000000, 0, 0}, @@ -4407,6 +4409,326 @@ const bagl_element_t ui_approval_blue[] = { }; +////////////////////////////////////////////////////////////////////////////// + +const bagl_element_t ui_verify_order_blue[] = { + {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, + 0x000000, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // erase screen (only under the status bar) + {{BAGL_RECTANGLE, 0x00, 0, 20, 320, 48, 0, 0, BAGL_FILL, COLOR_APP, + COLOR_APP, 0, 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + /// TOP STATUS BAR + {{BAGL_LABELINE, 0x60, 0, 45, 320, 30, 0, 0, BAGL_FILL, 0xFFFFFF, COLOR_APP, + BAGL_FONT_OPEN_SANS_SEMIBOLD_10_13PX | BAGL_FONT_ALIGNMENT_CENTER, 0}, + "CONFIRM SIGNATURE", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + // BADGE_TRANSACTION.GIF + {{BAGL_ICON, 0x40, 30, 98, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, + &C_badge_transaction, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x50, 100, 117, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + "Confirm", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABELINE, 0x50, 154, 117, 320, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, + (const char *)tmp_ctx.signing_context.ui.line1, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABELINE, 0x00, 100, 115, 320, 30, 0, 0, BAGL_FILL, 0x999999, + COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0}, + "Check and confirm data", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line4, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Amount asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line3, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "From", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.from, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Matcher", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line2, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Matcher Fee", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_amount, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 244, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Fee asset", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 244, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.fee_asset, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 257, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_LABEL, 0x71, 30, 322, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "Hash", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.txid, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE, 0x31, 30, 335, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 40, 414, 115, 36, 0, 18, + BAGL_FILL, 0xCCCCCC, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "REJECT", + 0, + 0xB7B7B7, + COLOR_BG_1, + io_seproxyhal_cancel, + NULL, + NULL}, + {{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 165, 414, 115, 36, 0, 18, + BAGL_FILL, 0x41ccb4, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_11_14PX | BAGL_FONT_ALIGNMENT_CENTER | + BAGL_FONT_ALIGNMENT_MIDDLE, + 0}, + "CONFIRM", + 0, + 0x3ab7a2, + COLOR_BG_1, + io_seproxyhal_touch_sign_approve, + NULL, + NULL}, + +}; + +////////////////////////////////////////////////////////////////////////////// + const bagl_element_t ui_address_blue[] = { {{BAGL_RECTANGLE, 0x00, 0, 68, 320, 413, 0, 0, BAGL_FILL, COLOR_BG_1, 0x000000, 0, 0}, @@ -4497,11 +4819,10 @@ unsigned int ui_address_blue_button(unsigned int button_mask, } unsigned int ui_verify_transfer_blue_button(unsigned int button_mask, - unsigned int button_mask_counter) { + unsigned int button_mask_counter) { return 0; } - unsigned int ui_verify_data_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; @@ -4563,9 +4884,8 @@ ui_verify_set_as_script_blue_button(unsigned int button_mask, return 0; } -unsigned int -ui_verify_invoke_blue_button(unsigned int button_mask, - unsigned int button_mask_counter) { +unsigned int ui_verify_invoke_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { return 0; } @@ -4575,6 +4895,11 @@ ui_verify_update_asset_blue_button(unsigned int button_mask, return 0; } +unsigned int ui_verify_order_blue_button(unsigned int button_mask, + unsigned int button_mask_counter) { + return 0; +} + unsigned int ui_approval_blue_button(unsigned int button_mask, unsigned int button_mask_counter) { return 0; diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index 751ff745..ad9fb5ef 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -904,11 +904,72 @@ UX_STEP_VALID(ux_invoke_13_step, pb, io_seproxyhal_cancel(NULL), "Reject", }); -UX_FLOW(ux_invoke_flow, &ux_invoke_1_step, &ux_invoke_2_step, - &ux_invoke_3_step, &ux_invoke_4_step, &ux_invoke_5_step, - &ux_invoke_6_step, &ux_invoke_7_step, &ux_invoke_8_step, - &ux_invoke_9_step, &ux_invoke_10_step, &ux_invoke_11_step, - &ux_invoke_12_step, &ux_invoke_13_step); +UX_FLOW(ux_invoke_flow, &ux_invoke_1_step, &ux_invoke_2_step, &ux_invoke_3_step, + &ux_invoke_4_step, &ux_invoke_5_step, &ux_invoke_6_step, + &ux_invoke_7_step, &ux_invoke_8_step, &ux_invoke_9_step, + &ux_invoke_10_step, &ux_invoke_11_step, &ux_invoke_12_step, + &ux_invoke_13_step); + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_order_1_step, pnn, + { + &C_icon_eye, + "Confirm", + (const char *)tmp_ctx.signing_context.ui.line1, + }); +UX_STEP_NOCB(ux_order_2_step, bnnn_paging, + { + .title = "Amount", + .text = (const char *)tmp_ctx.signing_context.ui.line4, + }); +UX_STEP_NOCB(ux_order_3_step, bnnn_paging, + { + .title = "Amount asset", + .text = (const char *)tmp_ctx.signing_context.ui.line3, + }); +UX_STEP_NOCB(ux_order_4_step, bnnn_paging, + { + .title = "From", + .text = (const char *)tmp_ctx.signing_context.ui.from, + }); +UX_STEP_NOCB(ux_order_5_step, bnnn_paging, + { + .title = "Matcher", + .text = (const char *)tmp_ctx.signing_context.ui.line2, + }); +UX_STEP_NOCB(ux_order_6_step, bnnn_paging, + { + .title = "Matcher Fee", + .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, + }); +UX_STEP_NOCB(ux_order_7_step, bnnn_paging, + { + .title = "Fee asset", + .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, + }); + +UX_STEP_NOCB(ux_order_8_step, bnnn_paging, + { + .title = "Hash", + .text = (const char *)tmp_ctx.signing_context.ui.txid, + }); +UX_STEP_VALID(ux_order_9_step, pbb, io_seproxyhal_touch_sign_approve(NULL), + { + &C_icon_validate_14, + "Accept", + "and send", + }); +UX_STEP_VALID(ux_order_10_step, pb, io_seproxyhal_cancel(NULL), + { + &C_icon_crossmark, + "Reject", + }); + +UX_FLOW(ux_order_flow, &ux_order_1_step, &ux_order_2_step, &ux_order_3_step, + &ux_order_4_step, &ux_order_5_step, &ux_order_6_step, &ux_order_7_step, + &ux_order_8_step, &ux_order_9_step, &ux_order_10_step); + ////////////////////////////////////////////////////////////////////// UX_STEP_NOCB(ux_verify_transaction_1_step, bnnn_paging, diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 80af4f83..b66d6e7c 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -107,16 +107,17 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { } bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, -void **arg) { + void **arg) { unsigned char buff[45]; uint32_t name_len; int len = stream->bytes_left; - if (!pb_read(stream, buff, 7)) { // read setting 3 bytes and 4 byte of function name size + if (!pb_read(stream, buff, + 7)) { // read setting 3 bytes and 4 byte of function name size return false; } len -= 7; name_len = deserialize_uint32_t(&buff[3]); - if(name_len > 41) { //if function name len is + if (name_len > 41) { // if function name len is if (!pb_read(stream, buff, 41)) { // read 41 byte of the name return false; } @@ -132,35 +133,37 @@ void **arg) { } len -= name_len; os_memmove((char *)*arg, buff, 45); - if (!pb_read(stream, NULL, len)) { // read setting 3 bytes and 4 byte of function name size + if (!pb_read( + stream, NULL, + len)) { // read setting 3 bytes and 4 byte of function name size return false; } } return true; } -bool copy_amount(uint64_t amount, int decimals, unsigned char * out) { +bool copy_amount(uint64_t amount, int decimals, unsigned char *out) { return print_amount(amount, decimals, out, 20); } bool amount_callback(pb_istream_t *stream, const pb_field_t *field, -void **arg) { + void **arg) { uint64_t value; if (!pb_decode_varint(stream, &value)) - return false; - return copy_amount(value, tmp_ctx.signing_context.amount_decimals, (unsigned char *)*arg); + return false; + return copy_amount(value, tmp_ctx.signing_context.amount_decimals, + (unsigned char *)*arg); } bool amount2_callback(pb_istream_t *stream, const pb_field_t *field, -void **arg) { + void **arg) { uint64_t value; if (!pb_decode_varint(stream, &value)) - return false; - return copy_amount(value, tmp_ctx.signing_context.amount2_decimals, (unsigned char *)*arg); + return false; + return copy_amount(value, tmp_ctx.signing_context.amount2_decimals, + (unsigned char *)*arg); } - - bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { if (field->tag == waves_Transaction_transfer_tag) { @@ -221,7 +224,7 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, tx->payments[0].asset_id.arg = &tmp_ctx.signing_context.ui.line1; tx->payments[1].asset_id.funcs.decode = asset_callback; tx->payments[1].asset_id.arg = &tmp_ctx.signing_context.ui.line5; - } + } return true; } @@ -277,22 +280,25 @@ void make_sponsorship_ui(waves_Transaction *tx) { } void make_invoke_ui(waves_Transaction *tx) { - if(tx->data.invoke_script.payments_count >= 1) { - print_amount(tx->data.invoke_script.payments[0].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line4, 20); + if (tx->data.invoke_script.payments_count >= 1) { + print_amount(tx->data.invoke_script.payments[0].amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)&tmp_ctx.signing_context.ui.line4, 20); } - if(tx->data.invoke_script.payments_count == 2) { - print_amount(tx->data.invoke_script.payments[1].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line6, 20); + if (tx->data.invoke_script.payments_count == 2) { + print_amount(tx->data.invoke_script.payments[1].amount, + tmp_ctx.signing_context.amount_decimals, + (unsigned char *)&tmp_ctx.signing_context.ui.line6, 20); } } -void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, - uint8_t init_buffer_size, uint16_t total_buffer_size) { +void build_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, + uint16_t total_buffer_size) { uint8_t status; // init variable for parsing waves_Transaction tx = waves_Transaction_init_default; - // set callback for parsing tx data + // set callback for parsing tx data field(transactions) tx.cb_data.funcs.decode = transaction_data_callback; - tx.sender_public_key.funcs.decode = from_callback; tx.sender_public_key.arg = &tmp_ctx.signing_context.ui.from; tx.fee.asset_id.funcs.decode = asset_callback; @@ -300,17 +306,17 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, // create stream for parsing pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, total_buffer_size); - //decoding tx message + // decoding tx message status = pb_decode(&stream, waves_Transaction_fields, &tx); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } - + print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); unsigned char tx_type = tmp_ctx.signing_context.data_type; - //prepeare non callback data for viewing depend on tx type + // prepeare non callback data for viewing depend on tx type if (tx_type == 3) { make_issue_ui(&tx); } else if (tx_type == 4) { @@ -326,7 +332,56 @@ void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, } else if (tx_type == 16) { make_invoke_ui(&tx); } - //finish parsing and view data + // finish parsing and view data + tmp_ctx.signing_context.step = 7; + tmp_ctx.signing_context.ui.finished = true; +} + +void build_order(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size) { + uint8_t status; + // init variable for parsing + waves_Order order = waves_Order_init_default; + order.sender_public_key.funcs.decode = from_callback; + order.sender_public_key.arg = &tmp_ctx.signing_context.ui.from; + order.matcher_public_key.funcs.decode = from_callback; + order.matcher_public_key.arg = &tmp_ctx.signing_context.ui.line2; + order.matcher_fee.asset_id.funcs.decode = asset_callback; + order.matcher_fee.asset_id.arg = &tmp_ctx.signing_context.ui.fee_asset; + order.asset_pair.amount_asset_id.funcs.decode = asset_callback; + order.asset_pair.amount_asset_id.arg = &tmp_ctx.signing_context.ui.line3; + // create stream for parsing + pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, + total_buffer_size); + // decoding tx message + status = pb_decode(&stream, waves_Order_fields, &order); + if (!status) { + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + THROW(0x6D00); + } + + print_amount(order.amount, tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line4, 20); + print_amount(order.matcher_fee.amount, tmp_ctx.signing_context.fee_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); + if (order.order_side == waves_Order_Side_BUY) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line1, + &"Buy order\0", 10); + } else { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line1, + &"Sell order\0", 11); + } + + // finish parsing and view data tmp_ctx.signing_context.step = 7; tmp_ctx.signing_context.ui.finished = true; } + +void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size) { + if (tmp_ctx.signing_context.data_type == 252) { + build_order(ctx, init_buffer, init_buffer_size, total_buffer_size); + } else { + build_tx(ctx, init_buffer, init_buffer_size, total_buffer_size); + } +} diff --git a/src/ui/transactions/protobuf.h b/src/ui/transactions/protobuf.h index 688a6dae..06094731 100644 --- a/src/ui/transactions/protobuf.h +++ b/src/ui/transactions/protobuf.h @@ -26,6 +26,7 @@ #include "../../nanopb/pb.h" #include "../../nanopb/pb_decode.h" #include "../../nanopb/pb_custom.h" +#include "../../nanopb_stubs/order.pb.h" #include "../../nanopb_stubs/transaction.pb.h" void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, diff --git a/src/ui/ui.c b/src/ui/ui.c index d903c229..fa434606 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -323,6 +323,13 @@ void show_sign_protobuf_ui() { UX_DISPLAY(ui_verify_update_asset_blue, NULL); #else ux_flow_init(0, ux_update_asset_flow, NULL); +#endif // #if TARGET_ID + } else if (tx_type == 252) { + ux_step_count = 8; +#if defined(TARGET_BLUE) + UX_DISPLAY(ui_verify_order_blue, NULL); +#else + ux_flow_init(0, ux_order_flow, NULL); #endif // #if TARGET_ID } } From dfb4b906ab34842885ba10dad1a0f46d85325baf Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Tue, 30 Jun 2020 21:44:56 +0400 Subject: [PATCH 18/26] fix error with memory --- python/ledger-waves.py | 5 +- src/main.c | 2 +- src/main.h | 13 ++-- src/ui/blue/ui_menus_blue.h | 36 +++++----- src/ui/nanox/ui_menus_nanox.h | 36 +++++----- src/ui/transactions/protobuf.c | 127 ++++++++++++++------------------- src/ui/transactions/protobuf.h | 4 +- src/ui/ui.c | 11 ++- 8 files changed, 111 insertions(+), 123 deletions(-) diff --git a/python/ledger-waves.py b/python/ledger-waves.py index b7c4b808..b01acbac 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -386,8 +386,8 @@ def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, versi timestamp = int(time.time() * 1000) list = [] for x in range(1): - k = "j" + str(x) - s = "jjjjjjj" + str(x) + k = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) + s = "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj" + str(x) dataEntery = tpb.DataTransactionData.DataEntry(key=k, string_value=s) list.append(dataEntery) data = tpb.DataTransactionData(data=list) @@ -659,7 +659,6 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am 1526477921829, 3 ) - # elif (select == "7"): elif (select == "8"): some_transfer_bytes = build_lease_protobuf( diff --git a/src/main.c b/src/main.c index 46684721..c96f865d 100644 --- a/src/main.c +++ b/src/main.c @@ -273,7 +273,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, THROW(SW_SIGN_DATA_NOT_MATCH); } size_t length = 45; - if (!b58enc((char *)tmp_ctx.signing_context.ui.txid, &length, + if (!b58enc((char *)tmp_ctx.signing_context.first_data_hash, &length, (const void *)&tmp_ctx.signing_context.first_data_hash, 32)) { THROW(SW_CONDITIONS_NOT_SATISFIED); diff --git a/src/main.h b/src/main.h index 5c4ed49f..eb2abc4b 100644 --- a/src/main.h +++ b/src/main.h @@ -77,7 +77,7 @@ typedef struct uiProtobuf_t { uint16_t total_size; // total size of the nanopb structure being received uint16_t total_received; // number of bytes received since decoding began uint16_t total_read; // number of bytes readed since decoding began - uint8_t data[150]; // size of the biggest nanopb element serialized + uint8_t data[160]; // size of the biggest nanopb element serialized } uiProtobuf_t; // A place to store information about the transaction @@ -88,18 +88,17 @@ typedef struct uiContext_t { uiByte_t byte; uiProtobuf_t proto; }; - unsigned char tmp[20]; - unsigned char txid[45]; - unsigned char from[45]; - unsigned char fee_amount[20]; + unsigned char from[36]; unsigned char fee_asset[45]; unsigned char line1[45]; unsigned char line2[45]; unsigned char - line3[45]; // reserved for recipient if transaction has resipient message + line3[36]; // reserved for recipient if transaction has recipient message unsigned char line4[45]; unsigned char line5[45]; unsigned char line6[20]; + unsigned char fee_amount[20]; + unsigned char tmp[20]; bool pkhash; bool finished; cx_blake2b_t hash_ctx; @@ -119,7 +118,7 @@ typedef struct signingContext_t { unsigned char data_version; unsigned char network_byte; unsigned char signature[64]; - unsigned char first_data_hash[32]; + unsigned char first_data_hash[45]; uint8_t step; uint8_t sign_from; uint32_t bip32[5]; diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index 0209ac71..1c3726bc 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -418,7 +418,7 @@ const bagl_element_t ui_verify_transfer_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -643,7 +643,7 @@ const bagl_element_t ui_verify_data_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -1023,7 +1023,7 @@ const bagl_element_t ui_verify_issue_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -1341,7 +1341,7 @@ const bagl_element_t ui_verify_reissue_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -1628,7 +1628,7 @@ const bagl_element_t ui_verify_burn_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -1915,7 +1915,7 @@ const bagl_element_t ui_verify_lease_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -2171,7 +2171,7 @@ const bagl_element_t ui_verify_cancel_lease_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -2427,7 +2427,7 @@ const bagl_element_t ui_verify_create_alias_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -2714,7 +2714,7 @@ const bagl_element_t ui_verify_masstransfer_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -2939,7 +2939,7 @@ const bagl_element_t ui_verify_set_ac_script_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -3226,7 +3226,7 @@ const bagl_element_t ui_verify_sponsorship_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -3482,7 +3482,7 @@ const bagl_element_t ui_verify_set_as_script_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -3676,7 +3676,7 @@ const bagl_element_t ui_verify_update_asset_blue[] = { {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.line3, + (const char *)tmp_ctx.signing_context.ui.line4, 0, 0, 0, @@ -3800,7 +3800,7 @@ const bagl_element_t ui_verify_update_asset_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -4211,7 +4211,7 @@ const bagl_element_t ui_verify_invoke_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, @@ -4465,7 +4465,7 @@ const bagl_element_t ui_verify_order_blue[] = { NULL}, {{BAGL_LABELINE, 0x50, 154, 117, 320, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX, 0}, - (const char *)tmp_ctx.signing_context.ui.line1, + (const char *)tmp_ctx.signing_context.ui.line3, 0, 0, 0, @@ -4527,7 +4527,7 @@ const bagl_element_t ui_verify_order_blue[] = { {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.line3, + (const char *)tmp_ctx.signing_context.ui.line1, 0, 0, 0, @@ -4682,7 +4682,7 @@ const bagl_element_t ui_verify_order_blue[] = { {{BAGL_LABEL, 0x11, 130, 322, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.txid, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index ad9fb5ef..bee78b0b 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -134,7 +134,7 @@ UX_STEP_NOCB(ux_transfer_8_step, bnnn_paging, UX_STEP_NOCB(ux_transfer_9_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_transfer_10_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -180,7 +180,7 @@ UX_STEP_NOCB(ux_data_4_step, bnnn_paging, UX_STEP_NOCB(ux_data_5_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_data_6_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -249,7 +249,7 @@ UX_STEP_NOCB(ux_issue_9_step, bnnn_paging, UX_STEP_NOCB(ux_issue_10_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_issue_11_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -310,7 +310,7 @@ UX_STEP_NOCB(ux_reissue_7_step, bnnn_paging, UX_STEP_NOCB(ux_reissue_8_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_reissue_9_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -366,7 +366,7 @@ UX_STEP_NOCB(ux_burn_6_step, bnnn_paging, UX_STEP_NOCB(ux_burn_7_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_burn_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -421,7 +421,7 @@ UX_STEP_NOCB(ux_lease_6_step, bnnn_paging, UX_STEP_NOCB(ux_lease_7_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_lease_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -471,7 +471,7 @@ UX_STEP_NOCB(ux_cancel_lease_5_step, bnnn_paging, UX_STEP_NOCB(ux_cancel_lease_6_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_cancel_lease_7_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -523,7 +523,7 @@ UX_STEP_NOCB(ux_create_alias_5_step, bnnn_paging, UX_STEP_NOCB(ux_create_alias_6_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_create_alias_7_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -582,7 +582,7 @@ UX_STEP_NOCB(ux_masstransfer_6_step, bnnn_paging, UX_STEP_NOCB(ux_masstransfer_7_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_masstransfer_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -630,7 +630,7 @@ UX_STEP_NOCB(ux_set_ac_script_4_step, bnnn_paging, UX_STEP_NOCB(ux_set_ac_script_5_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_set_ac_script_6_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -682,7 +682,7 @@ UX_STEP_NOCB(ux_set_as_script_5_step, bnnn_paging, UX_STEP_NOCB(ux_set_as_script_6_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_set_as_script_7_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -740,7 +740,7 @@ UX_STEP_NOCB(ux_sponsorship_6_step, bnnn_paging, UX_STEP_NOCB(ux_sponsorship_7_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_sponsorship_8_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -781,7 +781,7 @@ UX_STEP_NOCB(ux_update_asset_3_step, bnnn_paging, UX_STEP_NOCB(ux_update_asset_4_step, bnnn_paging, { .title = "Description", - .text = (const char *)tmp_ctx.signing_context.ui.line3, + .text = (const char *)tmp_ctx.signing_context.ui.line4, }); UX_STEP_NOCB(ux_update_asset_5_step, bnnn_paging, { @@ -802,7 +802,7 @@ UX_STEP_NOCB(ux_update_asset_7_step, bnnn_paging, UX_STEP_NOCB(ux_update_asset_8_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_update_asset_9_step, pbb, io_seproxyhal_touch_sign_approve(NULL), @@ -890,7 +890,7 @@ UX_STEP_NOCB(ux_invoke_10_step, bnnn_paging, UX_STEP_NOCB(ux_invoke_11_step, bnnn_paging, { .title = "Transaction Id", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_invoke_12_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { @@ -916,7 +916,7 @@ UX_STEP_NOCB(ux_order_1_step, pnn, { &C_icon_eye, "Confirm", - (const char *)tmp_ctx.signing_context.ui.line1, + (const char *)tmp_ctx.signing_context.ui.line3, }); UX_STEP_NOCB(ux_order_2_step, bnnn_paging, { @@ -926,7 +926,7 @@ UX_STEP_NOCB(ux_order_2_step, bnnn_paging, UX_STEP_NOCB(ux_order_3_step, bnnn_paging, { .title = "Amount asset", - .text = (const char *)tmp_ctx.signing_context.ui.line3, + .text = (const char *)tmp_ctx.signing_context.ui.line1, }); UX_STEP_NOCB(ux_order_4_step, bnnn_paging, { @@ -952,7 +952,7 @@ UX_STEP_NOCB(ux_order_7_step, bnnn_paging, UX_STEP_NOCB(ux_order_8_step, bnnn_paging, { .title = "Hash", - .text = (const char *)tmp_ctx.signing_context.ui.txid, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_VALID(ux_order_9_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index b66d6e7c..123f26c4 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -29,141 +29,126 @@ bool waves_Recipient_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field) { if (istream) { + PRINTF("Start Recipient callback\n"); int len = istream->bytes_left; - unsigned char buff[len]; - if (!pb_read(istream, buff, (size_t)istream->bytes_left)) { + os_memset(&G_io_apdu_buffer, 0, len); + if (!pb_read(istream, G_io_apdu_buffer, (size_t)istream->bytes_left)) { return false; } if (field->tag == waves_Recipient_public_key_hash_tag) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, buff, len); + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, G_io_apdu_buffer, len); tmp_ctx.signing_context.ui.pkhash = true; } else if (field->tag == waves_Recipient_alias_tag) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, buff, len); + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, G_io_apdu_buffer, len); } + PRINTF("End Recipient callback\n"); } return true; } bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { + PRINTF("Start asset callback\n"); size_t length = 45; int len = stream->bytes_left; - unsigned char buff[len]; - if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer, 0, len); + if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { return false; } if (len == 32) { - if (!b58enc((char *)*arg, &length, (const void *)buff, 32)) { + if (!b58enc((char *)*arg, &length, (const void *)G_io_apdu_buffer, 32)) { return false; } } else { os_memmove((char *)*arg, WAVES_CONST, 5); } + PRINTF("End asset callback\n"); return true; } bool from_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - unsigned char buff[32]; - - if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer, 0, 32); + PRINTF("Start from callback\n"); + if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, buff, 32); + os_memmove((char *)*arg, G_io_apdu_buffer, 32); + PRINTF("End from callback\n"); return true; } bool string_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - int strlen = stream->bytes_left; - unsigned char buff[strlen]; - if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + PRINTF("Start string callback\n"); + int len = stream->bytes_left; + os_memset(&G_io_apdu_buffer, 0, len); + if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, buff, strlen); + os_memmove((char *)*arg, G_io_apdu_buffer, len); + PRINTF("End string callback\n"); return true; } bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - int strlen = stream->bytes_left; - if (strlen > 41) { + int len = stream->bytes_left; + PRINTF("Start text callback\n"); + if (len > 41) { size_t length = 41; - unsigned char buff[45]; + os_memset(&G_io_apdu_buffer, 0, 45); size_t left = stream->bytes_left - length; - if (!pb_read(stream, buff, length)) { + if (!pb_read(stream, G_io_apdu_buffer, length)) { return false; } if (!pb_read(stream, NULL, left)) { return false; } - os_memmove((char *)&buff[41], &"...\0", 4); - os_memmove((char *)*arg, buff, 45); + os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); + os_memmove((char *)*arg, G_io_apdu_buffer, 45); } else { - unsigned char buff[strlen]; - if (!pb_read(stream, buff, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer, 0, len); + if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, buff, strlen); + os_memmove((char *)*arg, G_io_apdu_buffer, len); } + PRINTF("End text callback\n"); return true; } bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - unsigned char buff[45]; uint32_t name_len; + os_memset(&G_io_apdu_buffer, 0, 45); int len = stream->bytes_left; - if (!pb_read(stream, buff, + if (!pb_read(stream, G_io_apdu_buffer, 7)) { // read setting 3 bytes and 4 byte of function name size return false; } len -= 7; - name_len = deserialize_uint32_t(&buff[3]); + name_len = deserialize_uint32_t(&G_io_apdu_buffer[3]); if (name_len > 41) { // if function name len is - if (!pb_read(stream, buff, 41)) { // read 41 byte of the name + if (!pb_read(stream, G_io_apdu_buffer, 41)) { // read 41 byte of the name return false; } len -= 41; - os_memmove((char *)&buff[41], &"...\0", 4); - os_memmove((char *)*arg, buff, 45); + os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); + os_memmove((char *)*arg, G_io_apdu_buffer, 45); if (!pb_read(stream, NULL, len)) { // read last str to null return false; } } else { - if (!pb_read(stream, buff, name_len)) { // read all name str + if (!pb_read(stream, G_io_apdu_buffer, name_len)) { // read all name str return false; } len -= name_len; - os_memmove((char *)*arg, buff, 45); - if (!pb_read( - stream, NULL, - len)) { // read setting 3 bytes and 4 byte of function name size + os_memmove((char *)*arg, G_io_apdu_buffer, 45); + if (!pb_read(stream, NULL, len)) { //read other data return false; } } return true; } -bool copy_amount(uint64_t amount, int decimals, unsigned char *out) { - return print_amount(amount, decimals, out, 20); -} - -bool amount_callback(pb_istream_t *stream, const pb_field_t *field, - void **arg) { - uint64_t value; - if (!pb_decode_varint(stream, &value)) - return false; - return copy_amount(value, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)*arg); -} - -bool amount2_callback(pb_istream_t *stream, const pb_field_t *field, - void **arg) { - uint64_t value; - if (!pb_decode_varint(stream, &value)) - return false; - return copy_amount(value, tmp_ctx.signing_context.amount2_decimals, - (unsigned char *)*arg); -} - bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { if (field->tag == waves_Transaction_transfer_tag) { @@ -174,7 +159,7 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, tx->attachment.arg = &tmp_ctx.signing_context.ui.line4; } else if (field->tag == waves_Transaction_issue_tag) { waves_IssueTransactionData *tx = field->pData; - tx->name.funcs.decode = string_callback; + tx->name.funcs.decode = text_callback; tx->name.arg = &tmp_ctx.signing_context.ui.line1; tx->description.funcs.decode = text_callback; tx->description.arg = &tmp_ctx.signing_context.ui.line2; @@ -215,7 +200,7 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, tx->name.funcs.decode = string_callback; tx->name.arg = &tmp_ctx.signing_context.ui.line2; tx->description.funcs.decode = text_callback; - tx->description.arg = &tmp_ctx.signing_context.ui.line3; + tx->description.arg = &tmp_ctx.signing_context.ui.line4; } else if (field->tag == waves_Transaction_invoke_script_tag) { waves_InvokeScriptTransactionData *tx = field->pData; tx->function_call.funcs.decode = function_call_callback; @@ -292,7 +277,7 @@ void make_invoke_ui(waves_Transaction *tx) { } } -void build_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, +void build_protobuf_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, uint16_t total_buffer_size) { uint8_t status; // init variable for parsing @@ -307,11 +292,13 @@ void build_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, total_buffer_size); // decoding tx message + PRINTF("Start decoding\n"); status = pb_decode(&stream, waves_Transaction_fields, &tx); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } + PRINTF("End decoding\n"); print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); @@ -337,7 +324,7 @@ void build_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, tmp_ctx.signing_context.ui.finished = true; } -void build_order(uiProtobuf_t *ctx, uint8_t *init_buffer, +void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, uint16_t total_buffer_size) { uint8_t status; // init variable for parsing @@ -349,26 +336,27 @@ void build_order(uiProtobuf_t *ctx, uint8_t *init_buffer, order.matcher_fee.asset_id.funcs.decode = asset_callback; order.matcher_fee.asset_id.arg = &tmp_ctx.signing_context.ui.fee_asset; order.asset_pair.amount_asset_id.funcs.decode = asset_callback; - order.asset_pair.amount_asset_id.arg = &tmp_ctx.signing_context.ui.line3; + order.asset_pair.amount_asset_id.arg = &tmp_ctx.signing_context.ui.line1; // create stream for parsing pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, total_buffer_size); // decoding tx message + PRINTF("Start decoding\n"); status = pb_decode(&stream, waves_Order_fields, &order); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(0x6D00); } - + PRINTF("End decoding\n"); print_amount(order.amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)tmp_ctx.signing_context.ui.line4, 20); print_amount(order.matcher_fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); if (order.order_side == waves_Order_Side_BUY) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line1, + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Buy order\0", 10); } else { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line1, + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Sell order\0", 11); } @@ -376,12 +364,3 @@ void build_order(uiProtobuf_t *ctx, uint8_t *init_buffer, tmp_ctx.signing_context.step = 7; tmp_ctx.signing_context.ui.finished = true; } - -void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, - uint8_t init_buffer_size, uint16_t total_buffer_size) { - if (tmp_ctx.signing_context.data_type == 252) { - build_order(ctx, init_buffer, init_buffer_size, total_buffer_size); - } else { - build_tx(ctx, init_buffer, init_buffer_size, total_buffer_size); - } -} diff --git a/src/ui/transactions/protobuf.h b/src/ui/transactions/protobuf.h index 06094731..cfc1bc17 100644 --- a/src/ui/transactions/protobuf.h +++ b/src/ui/transactions/protobuf.h @@ -29,7 +29,9 @@ #include "../../nanopb_stubs/order.pb.h" #include "../../nanopb_stubs/transaction.pb.h" -void build_protobuf_ui(uiProtobuf_t *ctx, uint8_t *init_buffer, +void build_protobuf_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size); +void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, uint16_t total_buffer_size); #endif \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index fa434606..6b015fdd 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -160,11 +160,20 @@ void make_allowed_ui_steps(bool is_last) { PRINTF("make_allowed_ui_steps start\n"); if (tmp_ctx.signing_context.data_version > 2) { // if protobuf if (tmp_ctx.signing_context.ui.finished != true) { - build_protobuf_ui( + if (tmp_ctx.signing_context.data_type == 252) { + build_protobuf_order( &tmp_ctx.signing_context.ui.proto, G_io_apdu_buffer + 5 + tmp_ctx.signing_context.chunk_used, G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used, tmp_ctx.signing_context.data_size); + } else { + build_protobuf_tx( + &tmp_ctx.signing_context.ui.proto, + G_io_apdu_buffer + 5 + tmp_ctx.signing_context.chunk_used, + G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used, + tmp_ctx.signing_context.data_size); + } + } else { THROW(SW_INS_NOT_SUPPORTED); } From 0591bb78a4615e875d807c42702d46de16fe4a1a Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 2 Jul 2020 12:03:39 +0400 Subject: [PATCH 19/26] add proto files --- generate_proto.sh | 13 ++++ proto/amount.proto | 9 +++ proto/order.options | 1 + proto/order.proto | 31 ++++++++ proto/recipient.proto | 14 ++++ proto/transaction.options | 16 ++++ proto/transaction.proto | 150 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100755 generate_proto.sh create mode 100644 proto/amount.proto create mode 100644 proto/order.options create mode 100644 proto/order.proto create mode 100644 proto/recipient.proto create mode 100644 proto/transaction.options create mode 100644 proto/transaction.proto diff --git a/generate_proto.sh b/generate_proto.sh new file mode 100755 index 00000000..70cd72c8 --- /dev/null +++ b/generate_proto.sh @@ -0,0 +1,13 @@ +NANOPB=../ledger-nanopb + +pushd proto +protoc --plugin=protoc-gen-nanopb=${NANOPB}/generator/protoc-gen-nanopb --nanopb_out=../src/nanopb_stubs -I. -I${NANOPB}/generator/proto/ *.proto +protoc --python_out=../src/py3_tests -I. -I${NANOPB}/generator/proto/ *.proto +popd + +if ! [ "$(ls src/nanopb)" ]; then + cd src/nanopb + cp ../../ledger-nanopb/*.c . + cp ../../ledger-nanopb/*.h . + cd .. +fi diff --git a/proto/amount.proto b/proto/amount.proto new file mode 100644 index 00000000..e3afef09 --- /dev/null +++ b/proto/amount.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +package waves; +option java_package = "com.wavesplatform.protobuf"; +option csharp_namespace = "Waves"; + +message Amount { + bytes asset_id = 1; + int64 amount = 2; +}; diff --git a/proto/order.options b/proto/order.options new file mode 100644 index 00000000..29f56735 --- /dev/null +++ b/proto/order.options @@ -0,0 +1 @@ +waves.Order.proofs type: FT_IGNORE diff --git a/proto/order.proto b/proto/order.proto new file mode 100644 index 00000000..d5388ee1 --- /dev/null +++ b/proto/order.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; +package waves; +option java_package = "com.wavesplatform.protobuf.order"; +option csharp_namespace = "Waves"; + +import "amount.proto"; + +message AssetPair { + bytes amount_asset_id = 1; + bytes price_asset_id = 2; +}; + +message Order { + enum Side { + BUY = 0; + SELL = 1; + }; + + int32 chain_id = 1; + bytes sender_public_key = 2; + bytes matcher_public_key = 3; + AssetPair asset_pair = 4; + Side order_side = 5; + int64 amount = 6; + int64 price = 7; + int64 timestamp = 8; + int64 expiration = 9; + Amount matcher_fee = 10; + int32 version = 11; + repeated bytes proofs = 12; +}; diff --git a/proto/recipient.proto b/proto/recipient.proto new file mode 100644 index 00000000..5681bd7d --- /dev/null +++ b/proto/recipient.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package waves; +option java_package = "com.wavesplatform.protobuf.transaction"; +option csharp_namespace = "Waves"; + +import "nanopb.proto"; + +message Recipient { + oneof recipient { + // First 20 bytes of the result of the Keccak256(Blake2b256(publicKey)) hashing function. + bytes public_key_hash = 1 [(nanopb).callback_datatype = "const char*"]; + string alias = 2 [(nanopb).callback_datatype = "const char*"]; + }; +}; diff --git a/proto/transaction.options b/proto/transaction.options new file mode 100644 index 00000000..db1c82aa --- /dev/null +++ b/proto/transaction.options @@ -0,0 +1,16 @@ +#Transaction filed sizes +waves.IssueTransactionData.script type: FT_IGNORE + +waves.SetAssetScriptTransactionData.script type: FT_IGNORE + +waves.SetScriptTransactionData.script type: FT_IGNORE + +waves.MassTransferTransactionData.transfers type: FT_IGNORE + +waves.InvokeScriptTransactionData.payments max_count: 2 + +waves.DataTransactionData.data type: FT_IGNORE +waves.DataTransactionData.DataEntry type: FT_IGNORE +waves.DataTransactionData.DataEntry.key type: FT_IGNORE +waves.DataTransactionData.DataEntry.binary_value type: FT_IGNORE +waves.DataTransactionData.DataEntry.string_value type: FT_IGNORE \ No newline at end of file diff --git a/proto/transaction.proto b/proto/transaction.proto new file mode 100644 index 00000000..a6321de5 --- /dev/null +++ b/proto/transaction.proto @@ -0,0 +1,150 @@ +syntax = "proto3"; +package waves; + +option java_package = "com.wavesplatform.protobuf.transaction"; +option csharp_namespace = "Waves"; + +import "nanopb.proto"; +import "amount.proto"; +import "recipient.proto"; +import "order.proto"; + +message SignedTransaction { + Transaction transaction = 1; + repeated bytes proofs = 2; +} + +message Transaction { + option (nanopb_msgopt).submsg_callback = true; + int32 chain_id = 1; + bytes sender_public_key = 2; + Amount fee = 3; + int64 timestamp = 4; + int32 version = 5; + + oneof data { + GenesisTransactionData genesis = 101; + PaymentTransactionData payment = 102; + IssueTransactionData issue = 103; + TransferTransactionData transfer = 104; + ReissueTransactionData reissue = 105; + BurnTransactionData burn = 106; + ExchangeTransactionData exchange = 107; + LeaseTransactionData lease = 108; + LeaseCancelTransactionData lease_cancel = 109; + CreateAliasTransactionData create_alias = 110; + MassTransferTransactionData mass_transfer = 111; + DataTransactionData data_transaction = 112; + SetScriptTransactionData set_script = 113; + SponsorFeeTransactionData sponsor_fee = 114; + SetAssetScriptTransactionData set_asset_script = 115; + InvokeScriptTransactionData invoke_script = 116; + UpdateAssetInfoTransactionData update_asset_info = 117; + }; +}; + +message GenesisTransactionData { + bytes recipient_address = 1; + int64 amount = 2; +}; + +message PaymentTransactionData { + bytes recipient_address = 1; + int64 amount = 2; +}; + +message TransferTransactionData { + Recipient recipient = 1; + Amount amount = 2; + bytes attachment = 3; +}; + +message CreateAliasTransactionData { + string alias = 1; +}; + +message DataTransactionData { + message DataEntry { + string key = 1; + oneof value { + int64 int_value = 10; + bool bool_value = 11; + bytes binary_value = 12; + string string_value = 13; + }; + }; + + repeated DataEntry data = 1; +}; + +message MassTransferTransactionData { + message Transfer { + option (nanopb_msgopt).skip_message = true; + Recipient recipient = 1; + int64 amount = 2; + }; + + bytes asset_id = 1; + repeated Transfer transfers = 2; + bytes attachment = 3; +}; + +message LeaseTransactionData { + Recipient recipient = 1; + int64 amount = 2; +}; + +message LeaseCancelTransactionData { + bytes lease_id = 1; +}; + +message BurnTransactionData { + Amount asset_amount = 1; +}; + +message IssueTransactionData { + string name = 1; + string description = 2; + int64 amount = 3; + int32 decimals = 4; + bool reissuable = 5; + bytes script = 6; +}; + +message ReissueTransactionData { + Amount asset_amount = 1; + bool reissuable = 2; +}; + +message SetAssetScriptTransactionData { + bytes asset_id = 1; + bytes script = 2; +}; + +message SetScriptTransactionData { + bytes script = 1; +}; + +message ExchangeTransactionData { + int64 amount = 1; + int64 price = 2; + int64 buy_matcher_fee = 3; + int64 sell_matcher_fee = 4; + repeated Order orders = 5; +}; + +message SponsorFeeTransactionData { + Amount min_fee = 1; +}; + +message InvokeScriptTransactionData { + Recipient d_app = 1; + bytes function_call = 2; + repeated Amount payments = 3; +} + +message UpdateAssetInfoTransactionData { + bytes asset_id = 1; + string name = 2; + string description = 3; +} \ No newline at end of file From 5e58c1c911fe349d58e14e7599bec316d4a97a21 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 30 Jul 2020 14:38:31 +0400 Subject: [PATCH 20/26] add tx type & version check, fix bug with memory, issue descr, amount --- .gitignore | 1 + generate_proto.sh | 2 +- proto/recipient.options | 2 + proto/recipient.proto | 6 +- proto/transaction.options | 16 +- proto/transaction.proto | 1 + python/ledger-waves.py | 157 ++++---- python/recipient_pb2.py | 16 +- python/transaction_pb2.py | 63 +-- src/main.c | 42 +- src/main.h | 15 +- src/nanopb/pb_custom.c | 12 +- src/nanopb_stubs/amount.pb.c | 3 + src/nanopb_stubs/amount.pb.h | 21 +- src/nanopb_stubs/order.pb.c | 5 + src/nanopb_stubs/order.pb.h | 117 +++--- src/nanopb_stubs/recipient.pb.c | 3 + src/nanopb_stubs/recipient.pb.h | 43 +- src/nanopb_stubs/transaction.pb.c | 40 +- src/nanopb_stubs/transaction.pb.h | 630 +++++++++++------------------- src/ui/blue/ui_menus_blue.h | 2 +- src/ui/nanox/ui_menus_nanox.h | 2 +- src/ui/transactions/protobuf.c | 90 +++-- src/ui/ui.c | 137 ++++++- src/ui/ui.h | 1 + 25 files changed, 715 insertions(+), 712 deletions(-) create mode 100644 proto/recipient.options diff --git a/.gitignore b/.gitignore index 199a053c..c57f2129 100644 --- a/.gitignore +++ b/.gitignore @@ -53,5 +53,6 @@ dkms.conf # Project-level stuff debug/ +ledger-nanopb/ .DS_Store *.pyc \ No newline at end of file diff --git a/generate_proto.sh b/generate_proto.sh index 70cd72c8..5e388dc5 100755 --- a/generate_proto.sh +++ b/generate_proto.sh @@ -2,7 +2,7 @@ NANOPB=../ledger-nanopb pushd proto protoc --plugin=protoc-gen-nanopb=${NANOPB}/generator/protoc-gen-nanopb --nanopb_out=../src/nanopb_stubs -I. -I${NANOPB}/generator/proto/ *.proto -protoc --python_out=../src/py3_tests -I. -I${NANOPB}/generator/proto/ *.proto +protoc --python_out=../python -I. -I${NANOPB}/generator/proto/ *.proto popd if ! [ "$(ls src/nanopb)" ]; then diff --git a/proto/recipient.options b/proto/recipient.options new file mode 100644 index 00000000..d492c87a --- /dev/null +++ b/proto/recipient.options @@ -0,0 +1,2 @@ +waves.Recipient.public_key_hash max_size:20 fixed_length:true +waves.Recipient.alias max_size:30 \ No newline at end of file diff --git a/proto/recipient.proto b/proto/recipient.proto index 5681bd7d..21ce9c15 100644 --- a/proto/recipient.proto +++ b/proto/recipient.proto @@ -3,12 +3,10 @@ package waves; option java_package = "com.wavesplatform.protobuf.transaction"; option csharp_namespace = "Waves"; -import "nanopb.proto"; - message Recipient { oneof recipient { // First 20 bytes of the result of the Keccak256(Blake2b256(publicKey)) hashing function. - bytes public_key_hash = 1 [(nanopb).callback_datatype = "const char*"]; - string alias = 2 [(nanopb).callback_datatype = "const char*"]; + bytes public_key_hash = 1; + string alias = 2; }; }; diff --git a/proto/transaction.options b/proto/transaction.options index db1c82aa..ad63a74f 100644 --- a/proto/transaction.options +++ b/proto/transaction.options @@ -1,4 +1,14 @@ #Transaction filed sizes +waves.*.chain_id type: FT_IGNORE +waves.*.timestamp type: FT_IGNORE +waves.*.version type: FT_IGNORE + +waves.GenesisTransactionData type: FT_IGNORE + +waves.PaymentTransactionData type: FT_IGNORE + +waves.ExchangeTransactionData type: FT_IGNORE + waves.IssueTransactionData.script type: FT_IGNORE waves.SetAssetScriptTransactionData.script type: FT_IGNORE @@ -9,8 +19,4 @@ waves.MassTransferTransactionData.transfers type: FT_IGNORE waves.InvokeScriptTransactionData.payments max_count: 2 -waves.DataTransactionData.data type: FT_IGNORE -waves.DataTransactionData.DataEntry type: FT_IGNORE -waves.DataTransactionData.DataEntry.key type: FT_IGNORE -waves.DataTransactionData.DataEntry.binary_value type: FT_IGNORE -waves.DataTransactionData.DataEntry.string_value type: FT_IGNORE \ No newline at end of file +waves.DataTransactionData.data type: FT_IGNORE \ No newline at end of file diff --git a/proto/transaction.proto b/proto/transaction.proto index a6321de5..39846999 100644 --- a/proto/transaction.proto +++ b/proto/transaction.proto @@ -65,6 +65,7 @@ message CreateAliasTransactionData { message DataTransactionData { message DataEntry { + option (nanopb_msgopt).skip_message = true; string key = 1; oneof value { int64 int_value = 10; diff --git a/python/ledger-waves.py b/python/ledger-waves.py index b01acbac..9f72e01a 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -37,7 +37,6 @@ # 'T' for testnet, 'W' for mainnet chain_id = 'W' - class colors: '''Colors class: reset all colors with colors.reset @@ -245,17 +244,16 @@ def build_transfer_protobuf(publicKey, recipient, asset, amount, attachment='', timestamp = int(time.time() * 1000) to = Recipient(public_key_hash=base58.b58decode(recipient)) amountTx = Amount(asset_id=(base58.b58decode( - asset.assetId) if asset else b'\0'), amount=amount) + asset.assetId) if asset else None), amount=amount) transfer = tpb.TransferTransactionData( recipient=to, amount=amountTx, attachment=attachment) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( - publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode(publicKey), fee=fee, timestamp=timestamp, version=version, transfer=transfer) return trx.SerializeToString() -def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version=3): +def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment='', feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) to = Recipient(public_key_hash=base58.b58decode(recipient)) @@ -267,10 +265,10 @@ def build_masstransfer_protobuf(publicKey, recipient, asset, amount, attachment= transfers.append(tpb.MassTransferTransactionData.Transfer( recipient=to, amount=amount)) mass_transfer = tpb.MassTransferTransactionData(asset_id=(base58.b58decode( - asset.assetId) if asset else b'\0'), transfers=transfers, attachment=attachment) + asset.assetId) if asset else None), transfers=transfers, attachment=attachment) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, mass_transfer=mass_transfer) return trx.SerializeToString() @@ -281,31 +279,31 @@ def build_issue_protobuf(publicKey, name, descr, amount, decimals, reissue, feeA issue = tpb.IssueTransactionData( name=name, description=descr, amount=amount, decimals=decimals, reissuable=reissue) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, issue=issue) return trx.SerializeToString() -def build_set_ac_script_protobuf(publicKey, script, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_set_ac_script_protobuf(publicKey, script, feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) scr = tpb.SetScriptTransactionData(script=script) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, set_script=scr) return trx.SerializeToString() -def build_set_as_script_protobuf(publicKey, asset, script, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_set_as_script_protobuf(publicKey, asset, script, feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) scr = tpb.SetAssetScriptTransactionData( asset_id=base58.b58decode(asset.assetId), script=script) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, set_asset_script=scr) return trx.SerializeToString() @@ -316,8 +314,8 @@ def build_reissue_protobuf(publicKey, asset, amount, re, feeAsset='', txFee=1000 amountTx = Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) reissue = tpb.ReissueTransactionData(asset_amount=amountTx, reissuable=re) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, reissue=reissue) return trx.SerializeToString() @@ -328,8 +326,8 @@ def build_burn_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, tim amountTx = Amount(asset_id=base58.b58decode(asset.assetId), amount=amount) burn = tpb.BurnTransactionData(asset_amount=amountTx) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, burn=burn) return trx.SerializeToString() @@ -340,8 +338,8 @@ def build_lease_protobuf(publicKey, to, amount, feeAsset='', txFee=100000, times recipient = Recipient(public_key_hash=base58.b58decode(to)) lease = tpb.LeaseTransactionData(recipient=recipient, amount=amount) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, lease=lease) return trx.SerializeToString() @@ -352,8 +350,8 @@ def build_cancel_lease_protobuf(publicKey, leaseId, feeAsset='', txFee=100000, t lease_cancel = tpb.LeaseCancelTransactionData( lease_id=base58.b58decode(leaseId)) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, lease_cancel=lease_cancel) return trx.SerializeToString() @@ -363,25 +361,25 @@ def build_creating_alias_protobuf(publicKey, alias, feeAsset='', txFee=100000, t timestamp = int(time.time() * 1000) alias = tpb.CreateAliasTransactionData(alias=alias) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, create_alias=alias) return trx.SerializeToString() -def build_update_asset_protobuf(publicKey, asset, name, description, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_update_asset_protobuf(publicKey, asset, name, description, feeAsset='', txFee=100000, timestamp=0, version=1): if timestamp == 0: timestamp = int(time.time() * 1000) update_asset = tpb.UpdateAssetInfoTransactionData( asset_id=base58.b58decode(asset.assetId), name=name, description=description) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, update_asset_info=update_asset) return trx.SerializeToString() -def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) list = [] @@ -393,25 +391,25 @@ def build_data_protobuf(publicKey, feeAsset='', txFee=100000, timestamp=0, versi data = tpb.DataTransactionData(data=list) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) if feeAsset else b''), amount=txFee) - trx = tpb.Transaction(chain_id=84, sender_public_key=base58.b58decode( + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, data_transaction=data) return trx.SerializeToString() -def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_sponsorship_protobuf(publicKey, asset, amount, feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) amountTx = Amount(asset_id=(base58.b58decode(asset.assetId) - if feeAsset else b'\0'), amount=amount) + if feeAsset else None), amount=amount) sponsorship = tpb.SponsorFeeTransactionData(min_fee=amountTx) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, sponsor_fee=sponsorship) return trx.SerializeToString() -def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amount2, feeAsset='', txFee=100000, timestamp=0, version=3): +def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amount2, feeAsset='', txFee=100000, timestamp=0, version=2): if timestamp == 0: timestamp = int(time.time() * 1000) amounts = [] @@ -424,8 +422,8 @@ def build_invoke_protobuf(publicKey, dapp, function, asset, amount, asset2, amou invoke = tpb.InvokeScriptTransactionData( d_app=to, function_call=function, payments=amounts) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) - trx = tpb.Transaction(chain_id=87, sender_public_key=base58.b58decode( + if feeAsset else None), amount=txFee) + trx = tpb.Transaction(chain_id=ord(chain_id), sender_public_key=base58.b58decode( publicKey), fee=fee, timestamp=timestamp, version=version, invoke_script=invoke) return trx.SerializeToString() @@ -434,14 +432,14 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am if timestamp == 0: timestamp = int(time.time() * 1000) fee = Amount(asset_id=(base58.b58decode(feeAsset.assetId) - if feeAsset else b'\0'), amount=txFee) + if feeAsset else None), amount=txFee) assetPair = opb.AssetPair( amount_asset_id=(base58.b58decode(amountAsset.assetId) - if amountAsset else b'\0'), + if amountAsset else None), price_asset_id=(base58.b58decode(priceAsset.assetId) - if priceAsset else b'\0'), + if priceAsset else None), ) - order = opb.Order(chain_id=87, sender_public_key=base58.b58decode(publicKey), matcher_public_key=base58.b58decode( + order = opb.Order(chain_id=ord(chain_id), sender_public_key=base58.b58decode(publicKey), matcher_public_key=base58.b58decode( matcherPK), asset_pair=assetPair, order_side=1, amount=amount, price=price, timestamp=timestamp, expiration=expiration, matcher_fee=fee, version=3) return order.SerializeToString() @@ -456,7 +454,10 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am sys.exit(0) sys.exc_clear() - print("") + tx = tpb.Transaction() + #tx.ParseFromString(base58.b58decode(" + # 8YifyLj9HucsDjXaLjPjUdb2kVVox3AyMaBjYAwzjkodkVQ5dEnXdYkPES6LVn9K3C2RGDCRAd69QYYRqL21T8xCKHGLhnvx5he1Mue22AQayB1qs7Q9vScYc4Dkqgo46BLmYU7KWBH5eDofqeD52e2o8hFbrnhYQ6Lzyg5Bt")) + #print(base58.b58encode(tx.transfer.amount.asset_id)) print(colors.fg.lightcyan + colors.bold + "Ledger Nano S - Waves test app" + colors.reset) print(colors.fg.white + @@ -587,7 +588,6 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am print(colors.fg.white + "\t 4. Transfer" + colors.reset) print(colors.fg.white + "\t 5. Reissue" + colors.reset) print(colors.fg.white + "\t 6. Burn" + colors.reset) - #print(colors.fg.white + "\t 7. Exchange" + colors.reset) print(colors.fg.white + "\t 8. Lease" + colors.reset) print(colors.fg.white + "\t 9. Lease Cancel" + colors.reset) print(colors.fg.white + "\t 10. Create Alias" + colors.reset) @@ -605,6 +605,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am decimals = 8 # tx amount asset decimals decimals2 = 0 feeDecimals = 8 # fee amount asset decimals + version = 3 if (select == "3"): decimals = 3 some_transfer_bytes = build_issue_protobuf( @@ -618,21 +619,24 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "4"): - decimals = 8 + decimals = 4 + feeDecimals = 4 + version = 3 + chain_id = 'R' some_transfer_bytes = build_transfer_protobuf( - # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt - '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', - "23edvPK94JRdmDj7rKwzLbu22Sem", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL - pw.Asset('B3mFpuCTpShBkSNiKaVbKeipktYWufEMAEGvBAdNP6tu'), - 100000000, - 'privet', - pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), - 100000, - 1526477921829, - 3 + # 3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF + 'AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV', + "Yx1KwZyaRFWaWZALgQ8D1Ft4sdd", # 3P8mkuJyiFvVRLjVNfDvdqVqH92bZZkQtAL + pw.Asset('9Z9DqJz4GbrJiMDHRFdGPz4GdVy6sWzzRQKZARkvsgMp'), + 9223372036854775807, + '', + None, + 100001, + 1600000000000, + version ) elif (select == "5"): decimals = 8 @@ -645,7 +649,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "6"): decimals = 8 @@ -657,7 +661,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "8"): @@ -669,7 +673,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "9"): some_transfer_bytes = build_cancel_lease_protobuf( @@ -679,7 +683,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "10"): some_transfer_bytes = build_creating_alias_protobuf( @@ -689,9 +693,10 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "11"): + version = 2 some_transfer_bytes = build_masstransfer_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', @@ -702,18 +707,20 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "12"): + version = 2 some_transfer_bytes = build_data_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "13"): + version = 2 script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") some_transfer_bytes = build_set_ac_script_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt @@ -722,10 +729,11 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "14"): decimals = 6 + version = 2 some_transfer_bytes = build_sponsorship_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', @@ -734,9 +742,10 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "15"): + version = 2 script = base64.b64decode("AAIDAAAAAAAAAAYIARIAEgAAAAAEAAAAAAVscEtleQIAAAALbGFzdFBheW1lbnQAAAAABWxpS2V5AgAAAApiZXN0Rm9tb2VyAAAAAAVsaEtleQIAAAAGaGVpZ2h0AAAAAANkYXkAAAAAAAAABaAAAAACAAAAAWkBAAAAC2ZlYXJtaXNzaW5nAAAAAAQAAAAHcGF5bWVudAQAAAAHJG1hdGNoMAgFAAAAAWkAAAAHcGF5bWVudAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAPQXR0YWNoZWRQYXltZW50BAAAAAFwBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCAUAAAABcAAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAApCeXRlVmVjdG9yBAAAAAdhc3NldElkBQAAAAckbWF0Y2gxCQAAAgAAAAECAAAAD2ZvbW8gd2F2ZXMgb25seQgFAAAAAXAAAAAGYW1vdW50CQAAAgAAAAECAAAAGHBheW1lbnQgbXVzdCBiZSBhdHRhY2hlZAQAAAALbGFzdFBheW1lbnQEAAAAByRtYXRjaDAJAAQaAAAAAgUAAAAEdGhpcwIAAAALbGFzdFBheW1lbnQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABcAUAAAAHJG1hdGNoMAUAAAABcAAAAAAAAAAAAAMJAABnAAAAAgUAAAALbGFzdFBheW1lbnQFAAAAB3BheW1lbnQJAAACAAAAAQkAASwAAAACAgAAAA9taW4gcGF5bWVudCBpcyAJAAGkAAAAAQUAAAAHcGF5bWVudAkBAAAACFdyaXRlU2V0AAAAAQkABEwAAAACCQEAAAAJRGF0YUVudHJ5AAAAAgUAAAAFbHBLZXkFAAAAB3BheW1lbnQJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAABWxpS2V5CAgFAAAAAWkAAAAGY2FsbGVyAAAABWJ5dGVzCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANuaWwAAAABaQEAAAAId2l0aGRyYXcAAAAABAAAAA1jYWxsZXJDb3JyZWN0CQAAAAAAAAIICAUAAAABaQAAAAZjYWxsZXIAAAAFYnl0ZXMJAQAAAAdleHRyYWN0AAAAAQkABBwAAAACBQAAAAR0aGlzBQAAAAVsaUtleQQAAAANaGVpZ2h0Q29ycmVjdAkAAGcAAAACCQAAZQAAAAIJAQAAAAdleHRyYWN0AAAAAQkABBoAAAACBQAAAAR0aGlzBQAAAAVsaEtleQUAAAAGaGVpZ2h0BQAAAANkYXkEAAAAC2NhbldpdGhkcmF3AwUAAAANaGVpZ2h0Q29ycmVjdAUAAAANY2FsbGVyQ29ycmVjdAcDBQAAAAtjYW5XaXRoZHJhdwkBAAAAC1RyYW5zZmVyU2V0AAAAAQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIJAQAAAAx3YXZlc0JhbGFuY2UAAAABBQAAAAR0aGlzBQAAAAR1bml0BQAAAANuaWwJAAACAAAAAQIAAAAGYmVob2xkAAAAACSiqig=") some_transfer_bytes = build_set_as_script_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt @@ -746,9 +755,10 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif (select == "16"): + version = 2 fname = "function_name" function_call = chr( 2) + chr(2) + "argument1".encode() + chr(2) + "argument2".encode() @@ -765,9 +775,14 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am 1000000, pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 1000000000, + pw.Asset('51LxAtwBXapvvTFSbbh4nLyWFxH6x8ocfNvrXxbTChze'), + 1000000, + 1526477921829, + version ) elif (select == "17"): + version = 1 some_transfer_bytes = build_update_asset_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', @@ -777,9 +792,10 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am pw.Asset('9gqcTyupiDWuogWhKv8G3EMwjMaobkw9Lpys4EY2F62t'), 100000, 1526477921829, - 3 + version ) elif(select == "252"): + version = 4 some_transfer_bytes = build_order_protobuf( # 3PDCeakWckRvK5vVeJnCy1R2rE1utBcJMwt '4ovEU8YpbHTurwzw8CDZaCD7m6LpyMTC4nrJcgDHb4Jh', @@ -794,7 +810,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am 1526477921829, '', # waves 100000, - 3 + version ) else: break @@ -806,7 +822,6 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am binary_data = path_to_bytes(expand_path(path)) print(colors.fg.lightgrey + "path bytes: " + base58.b58encode(str(path_to_bytes(expand_path(path))))) - # tx amount asset decimals binary_data += chr(decimals) # tx amount2 asset decimals @@ -820,7 +835,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am str(some_transfer_bytes)) + "\")> " + colors.reset) if len(input) == 0: # 2 first bytes aren't the tx data, but info type for the ledger - binary_data += chr(int(select)) + chr(3) + binary_data += chr(int(select)) + chr(version) binary_data += struct.pack(">I", len(some_transfer_bytes)) binary_data += some_transfer_bytes binary_data += some_transfer_bytes diff --git a/python/recipient_pb2.py b/python/recipient_pb2.py index d5399f5b..3bea0040 100644 --- a/python/recipient_pb2.py +++ b/python/recipient_pb2.py @@ -11,7 +11,6 @@ _sym_db = _symbol_database.Default() -import nanopb_pb2 as nanopb__pb2 DESCRIPTOR = _descriptor.FileDescriptor( @@ -19,9 +18,8 @@ package='waves', syntax='proto3', serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', - serialized_pb=b'\n\x0frecipient.proto\x12\x05waves\x1a\x0cnanopb.proto\"j\n\tRecipient\x12,\n\x0fpublic_key_hash\x18\x01 \x01(\x0c\x42\x11\x92?\x0e\x92\x01\x0b\x63onst char*H\x00\x12\"\n\x05\x61lias\x18\x02 \x01(\tB\x11\x92?\x0e\x92\x01\x0b\x63onst char*H\x00\x42\x0b\n\trecipientB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' - , - dependencies=[nanopb__pb2.DESCRIPTOR,]) + serialized_pb=b'\n\x0frecipient.proto\x12\x05waves\"D\n\tRecipient\x12\x19\n\x0fpublic_key_hash\x18\x01 \x01(\x0cH\x00\x12\x0f\n\x05\x61lias\x18\x02 \x01(\tH\x00\x42\x0b\n\trecipientB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' +) @@ -39,14 +37,14 @@ has_default_value=False, default_value=b"", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=b'\222?\016\222\001\013const char*', file=DESCRIPTOR), + serialized_options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='alias', full_name='waves.Recipient.alias', index=1, number=2, type=9, cpp_type=9, label=1, has_default_value=False, default_value=b"".decode('utf-8'), message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=b'\222?\016\222\001\013const char*', file=DESCRIPTOR), + serialized_options=None, file=DESCRIPTOR), ], extensions=[ ], @@ -62,8 +60,8 @@ name='recipient', full_name='waves.Recipient.recipient', index=0, containing_type=None, fields=[]), ], - serialized_start=40, - serialized_end=146, + serialized_start=26, + serialized_end=94, ) _RECIPIENT.oneofs_by_name['recipient'].fields.append( @@ -84,6 +82,4 @@ DESCRIPTOR._options = None -_RECIPIENT.fields_by_name['public_key_hash']._options = None -_RECIPIENT.fields_by_name['alias']._options = None # @@protoc_insertion_point(module_scope) diff --git a/python/transaction_pb2.py b/python/transaction_pb2.py index 6fd21705..1d2ad681 100644 --- a/python/transaction_pb2.py +++ b/python/transaction_pb2.py @@ -22,7 +22,7 @@ package='waves', syntax='proto3', serialized_options=b'\n&com.wavesplatform.protobuf.transaction\252\002\005Waves', - serialized_pb=b'\n\x11transaction.proto\x12\x05waves\x1a\x0cnanopb.proto\x1a\x0c\x61mount.proto\x1a\x0frecipient.proto\x1a\x0border.proto\"L\n\x11SignedTransaction\x12\'\n\x0btransaction\x18\x01 \x01(\x0b\x32\x12.waves.Transaction\x12\x0e\n\x06proofs\x18\x02 \x03(\x0c\"\xae\x08\n\x0bTransaction\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x03\x66\x65\x65\x18\x03 \x01(\x0b\x32\r.waves.Amount\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x0f\n\x07version\x18\x05 \x01(\x05\x12\x30\n\x07genesis\x18\x65 \x01(\x0b\x32\x1d.waves.GenesisTransactionDataH\x00\x12\x30\n\x07payment\x18\x66 \x01(\x0b\x32\x1d.waves.PaymentTransactionDataH\x00\x12,\n\x05issue\x18g \x01(\x0b\x32\x1b.waves.IssueTransactionDataH\x00\x12\x32\n\x08transfer\x18h \x01(\x0b\x32\x1e.waves.TransferTransactionDataH\x00\x12\x30\n\x07reissue\x18i \x01(\x0b\x32\x1d.waves.ReissueTransactionDataH\x00\x12*\n\x04\x62urn\x18j \x01(\x0b\x32\x1a.waves.BurnTransactionDataH\x00\x12\x32\n\x08\x65xchange\x18k \x01(\x0b\x32\x1e.waves.ExchangeTransactionDataH\x00\x12,\n\x05lease\x18l \x01(\x0b\x32\x1b.waves.LeaseTransactionDataH\x00\x12\x39\n\x0clease_cancel\x18m \x01(\x0b\x32!.waves.LeaseCancelTransactionDataH\x00\x12\x39\n\x0c\x63reate_alias\x18n \x01(\x0b\x32!.waves.CreateAliasTransactionDataH\x00\x12;\n\rmass_transfer\x18o \x01(\x0b\x32\".waves.MassTransferTransactionDataH\x00\x12\x36\n\x10\x64\x61ta_transaction\x18p \x01(\x0b\x32\x1a.waves.DataTransactionDataH\x00\x12\x35\n\nset_script\x18q \x01(\x0b\x32\x1f.waves.SetScriptTransactionDataH\x00\x12\x37\n\x0bsponsor_fee\x18r \x01(\x0b\x32 .waves.SponsorFeeTransactionDataH\x00\x12@\n\x10set_asset_script\x18s \x01(\x0b\x32$.waves.SetAssetScriptTransactionDataH\x00\x12;\n\rinvoke_script\x18t \x01(\x0b\x32\".waves.InvokeScriptTransactionDataH\x00\x12\x42\n\x11update_asset_info\x18u \x01(\x0b\x32%.waves.UpdateAssetInfoTransactionDataH\x00:\x06\x92?\x03\xb0\x01\x01\x42\x06\n\x04\x64\x61ta\"C\n\x16GenesisTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"C\n\x16PaymentTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"q\n\x17TransferTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x1d\n\x06\x61mount\x18\x02 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nattachment\x18\x03 \x01(\x0c\"+\n\x1a\x43reateAliasTransactionData\x12\r\n\x05\x61lias\x18\x01 \x01(\t\"\xc7\x01\n\x13\x44\x61taTransactionData\x12\x32\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32$.waves.DataTransactionData.DataEntry\x1a|\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\n \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x0b \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x0c \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\r \x01(\tH\x00\x42\x07\n\x05value\"\xcb\x01\n\x1bMassTransferTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12>\n\ttransfers\x18\x02 \x03(\x0b\x32+.waves.MassTransferTransactionData.Transfer\x12\x12\n\nattachment\x18\x03 \x01(\x0c\x1a\x46\n\x08Transfer\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03:\x05\x92?\x02\x30\x01\"K\n\x14LeaseTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\".\n\x1aLeaseCancelTransactionData\x12\x10\n\x08lease_id\x18\x01 \x01(\x0c\":\n\x13\x42urnTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\"\x7f\n\x14IssueTransactionData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x03\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x05\x12\x12\n\nreissuable\x18\x05 \x01(\x08\x12\x0e\n\x06script\x18\x06 \x01(\x0c\"Q\n\x16ReissueTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nreissuable\x18\x02 \x01(\x08\"A\n\x1dSetAssetScriptTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06script\x18\x02 \x01(\x0c\"*\n\x18SetScriptTransactionData\x12\x0e\n\x06script\x18\x01 \x01(\x0c\"\x89\x01\n\x17\x45xchangeTransactionData\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x03\x12\r\n\x05price\x18\x02 \x01(\x03\x12\x17\n\x0f\x62uy_matcher_fee\x18\x03 \x01(\x03\x12\x18\n\x10sell_matcher_fee\x18\x04 \x01(\x03\x12\x1c\n\x06orders\x18\x05 \x03(\x0b\x32\x0c.waves.Order\";\n\x19SponsorFeeTransactionData\x12\x1e\n\x07min_fee\x18\x01 \x01(\x0b\x32\r.waves.Amount\"v\n\x1bInvokeScriptTransactionData\x12\x1f\n\x05\x64_app\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x15\n\rfunction_call\x18\x02 \x01(\x0c\x12\x1f\n\x08payments\x18\x03 \x03(\x0b\x32\r.waves.Amount\"U\n\x1eUpdateAssetInfoTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\tB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' + serialized_pb=b'\n\x11transaction.proto\x12\x05waves\x1a\x0cnanopb.proto\x1a\x0c\x61mount.proto\x1a\x0frecipient.proto\x1a\x0border.proto\"L\n\x11SignedTransaction\x12\'\n\x0btransaction\x18\x01 \x01(\x0b\x32\x12.waves.Transaction\x12\x0e\n\x06proofs\x18\x02 \x03(\x0c\"\xae\x08\n\x0bTransaction\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x05\x12\x19\n\x11sender_public_key\x18\x02 \x01(\x0c\x12\x1a\n\x03\x66\x65\x65\x18\x03 \x01(\x0b\x32\r.waves.Amount\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x0f\n\x07version\x18\x05 \x01(\x05\x12\x30\n\x07genesis\x18\x65 \x01(\x0b\x32\x1d.waves.GenesisTransactionDataH\x00\x12\x30\n\x07payment\x18\x66 \x01(\x0b\x32\x1d.waves.PaymentTransactionDataH\x00\x12,\n\x05issue\x18g \x01(\x0b\x32\x1b.waves.IssueTransactionDataH\x00\x12\x32\n\x08transfer\x18h \x01(\x0b\x32\x1e.waves.TransferTransactionDataH\x00\x12\x30\n\x07reissue\x18i \x01(\x0b\x32\x1d.waves.ReissueTransactionDataH\x00\x12*\n\x04\x62urn\x18j \x01(\x0b\x32\x1a.waves.BurnTransactionDataH\x00\x12\x32\n\x08\x65xchange\x18k \x01(\x0b\x32\x1e.waves.ExchangeTransactionDataH\x00\x12,\n\x05lease\x18l \x01(\x0b\x32\x1b.waves.LeaseTransactionDataH\x00\x12\x39\n\x0clease_cancel\x18m \x01(\x0b\x32!.waves.LeaseCancelTransactionDataH\x00\x12\x39\n\x0c\x63reate_alias\x18n \x01(\x0b\x32!.waves.CreateAliasTransactionDataH\x00\x12;\n\rmass_transfer\x18o \x01(\x0b\x32\".waves.MassTransferTransactionDataH\x00\x12\x36\n\x10\x64\x61ta_transaction\x18p \x01(\x0b\x32\x1a.waves.DataTransactionDataH\x00\x12\x35\n\nset_script\x18q \x01(\x0b\x32\x1f.waves.SetScriptTransactionDataH\x00\x12\x37\n\x0bsponsor_fee\x18r \x01(\x0b\x32 .waves.SponsorFeeTransactionDataH\x00\x12@\n\x10set_asset_script\x18s \x01(\x0b\x32$.waves.SetAssetScriptTransactionDataH\x00\x12;\n\rinvoke_script\x18t \x01(\x0b\x32\".waves.InvokeScriptTransactionDataH\x00\x12\x42\n\x11update_asset_info\x18u \x01(\x0b\x32%.waves.UpdateAssetInfoTransactionDataH\x00:\x06\x92?\x03\xb0\x01\x01\x42\x06\n\x04\x64\x61ta\"C\n\x16GenesisTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"C\n\x16PaymentTransactionData\x12\x19\n\x11recipient_address\x18\x01 \x01(\x0c\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\"q\n\x17TransferTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x1d\n\x06\x61mount\x18\x02 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nattachment\x18\x03 \x01(\x0c\"+\n\x1a\x43reateAliasTransactionData\x12\r\n\x05\x61lias\x18\x01 \x01(\t\"\xcf\x01\n\x13\x44\x61taTransactionData\x12\x32\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32$.waves.DataTransactionData.DataEntry\x1a\x83\x01\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x13\n\tint_value\x18\n \x01(\x03H\x00\x12\x14\n\nbool_value\x18\x0b \x01(\x08H\x00\x12\x16\n\x0c\x62inary_value\x18\x0c \x01(\x0cH\x00\x12\x16\n\x0cstring_value\x18\r \x01(\tH\x00:\x05\x92?\x02\x30\x01\x42\x07\n\x05value\"\xcb\x01\n\x1bMassTransferTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12>\n\ttransfers\x18\x02 \x03(\x0b\x32+.waves.MassTransferTransactionData.Transfer\x12\x12\n\nattachment\x18\x03 \x01(\x0c\x1a\x46\n\x08Transfer\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03:\x05\x92?\x02\x30\x01\"K\n\x14LeaseTransactionData\x12#\n\trecipient\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x0e\n\x06\x61mount\x18\x02 \x01(\x03\".\n\x1aLeaseCancelTransactionData\x12\x10\n\x08lease_id\x18\x01 \x01(\x0c\":\n\x13\x42urnTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\"\x7f\n\x14IssueTransactionData\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0e\n\x06\x61mount\x18\x03 \x01(\x03\x12\x10\n\x08\x64\x65\x63imals\x18\x04 \x01(\x05\x12\x12\n\nreissuable\x18\x05 \x01(\x08\x12\x0e\n\x06script\x18\x06 \x01(\x0c\"Q\n\x16ReissueTransactionData\x12#\n\x0c\x61sset_amount\x18\x01 \x01(\x0b\x32\r.waves.Amount\x12\x12\n\nreissuable\x18\x02 \x01(\x08\"A\n\x1dSetAssetScriptTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0e\n\x06script\x18\x02 \x01(\x0c\"*\n\x18SetScriptTransactionData\x12\x0e\n\x06script\x18\x01 \x01(\x0c\"\x89\x01\n\x17\x45xchangeTransactionData\x12\x0e\n\x06\x61mount\x18\x01 \x01(\x03\x12\r\n\x05price\x18\x02 \x01(\x03\x12\x17\n\x0f\x62uy_matcher_fee\x18\x03 \x01(\x03\x12\x18\n\x10sell_matcher_fee\x18\x04 \x01(\x03\x12\x1c\n\x06orders\x18\x05 \x03(\x0b\x32\x0c.waves.Order\";\n\x19SponsorFeeTransactionData\x12\x1e\n\x07min_fee\x18\x01 \x01(\x0b\x32\r.waves.Amount\"v\n\x1bInvokeScriptTransactionData\x12\x1f\n\x05\x64_app\x18\x01 \x01(\x0b\x32\x10.waves.Recipient\x12\x15\n\rfunction_call\x18\x02 \x01(\x0c\x12\x1f\n\x08payments\x18\x03 \x03(\x0b\x32\r.waves.Amount\"U\n\x1eUpdateAssetInfoTransactionData\x12\x10\n\x08\x61sset_id\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\tB0\n&com.wavesplatform.protobuf.transaction\xaa\x02\x05Wavesb\x06proto3' , dependencies=[nanopb__pb2.DESCRIPTOR,amount__pb2.DESCRIPTOR,recipient__pb2.DESCRIPTOR,order__pb2.DESCRIPTOR,]) @@ -448,7 +448,7 @@ nested_types=[], enum_types=[ ], - serialized_options=None, + serialized_options=b'\222?\0020\001', is_extendable=False, syntax='proto3', extension_ranges=[], @@ -457,8 +457,8 @@ name='value', full_name='waves.DataTransactionData.DataEntry.value', index=0, containing_type=None, fields=[]), ], - serialized_start=1611, - serialized_end=1735, + serialized_start=1612, + serialized_end=1743, ) _DATATRANSACTIONDATA = _descriptor.Descriptor( @@ -488,7 +488,7 @@ oneofs=[ ], serialized_start=1536, - serialized_end=1735, + serialized_end=1743, ) @@ -525,8 +525,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1871, - serialized_end=1941, + serialized_start=1879, + serialized_end=1949, ) _MASSTRANSFERTRANSACTIONDATA = _descriptor.Descriptor( @@ -569,8 +569,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1738, - serialized_end=1941, + serialized_start=1746, + serialized_end=1949, ) @@ -607,8 +607,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1943, - serialized_end=2018, + serialized_start=1951, + serialized_end=2026, ) @@ -638,8 +638,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2020, - serialized_end=2066, + serialized_start=2028, + serialized_end=2074, ) @@ -669,8 +669,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2068, - serialized_end=2126, + serialized_start=2076, + serialized_end=2134, ) @@ -735,8 +735,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2128, - serialized_end=2255, + serialized_start=2136, + serialized_end=2263, ) @@ -773,8 +773,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2257, - serialized_end=2338, + serialized_start=2265, + serialized_end=2346, ) @@ -811,8 +811,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2340, - serialized_end=2405, + serialized_start=2348, + serialized_end=2413, ) @@ -842,8 +842,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2407, - serialized_end=2449, + serialized_start=2415, + serialized_end=2457, ) @@ -901,8 +901,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2452, - serialized_end=2589, + serialized_start=2460, + serialized_end=2597, ) @@ -932,8 +932,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2591, - serialized_end=2650, + serialized_start=2599, + serialized_end=2658, ) @@ -977,8 +977,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2652, - serialized_end=2770, + serialized_start=2660, + serialized_end=2778, ) @@ -1022,8 +1022,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=2772, - serialized_end=2857, + serialized_start=2780, + serialized_end=2865, ) _SIGNEDTRANSACTION.fields_by_name['transaction'].message_type = _TRANSACTION @@ -1295,5 +1295,6 @@ DESCRIPTOR._options = None _TRANSACTION._options = None +_DATATRANSACTIONDATA_DATAENTRY._options = None _MASSTRANSFERTRANSACTIONDATA_TRANSFER._options = None # @@protoc_insertion_point(module_scope) diff --git a/src/main.c b/src/main.c index c96f865d..27ecb813 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,16 @@ tmpContext_t tmp_ctx; // Non-volatile storage for the wallet app's stuff internal_storage_t const N_storage_real; +extern void _ebss; + + // Return true if there is less than MIN_BSS_STACK_GAP bytes available in the + // stack + void check_stack_overflow(int step) { + uint32_t stack_top = 0; + PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); + //PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); + } + // SPI Buffer for io_event unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; @@ -164,7 +174,15 @@ void make_allowed_sign_steps() { tmp_ctx.signing_context.data_type = G_io_apdu_buffer[28]; tmp_ctx.signing_context.data_version = G_io_apdu_buffer[29]; tmp_ctx.signing_context.data_size = - deserialize_uint32_t(&G_io_apdu_buffer[30]); + deserialize_uint32_t(&G_io_apdu_buffer[30]); + // getting message type based on tx type and varsion + tmp_ctx.signing_context.message_type = getMessageType(); + if(tmp_ctx.signing_context.amount_decimals < 0 || tmp_ctx.signing_context.amount_decimals > 8 ) { + THROW(SW_INCORRECT_PRECISION_VALUE); + } + if(tmp_ctx.signing_context.amount2_decimals < 0 || tmp_ctx.signing_context.amount2_decimals > 8) { + THROW(SW_INCORRECT_PRECISION_VALUE); + } } while (tmp_ctx.signing_context.chunk_used < chunk_data_size && @@ -262,14 +280,15 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } else { make_allowed_ui_steps(false); } - - if (tmp_ctx.signing_context.step == - 7) { // all data parsed and prepeared to view - unsigned char third_data_hash[64]; + // all data parsed and prepeared to view + if (tmp_ctx.signing_context.step == 7) { + os_memset(&G_io_apdu_buffer, 0, 64); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, - third_data_hash, 32); + G_io_apdu_buffer, 32); + // check view data eq to signed data if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, - &third_data_hash, 32) != 0) { + &G_io_apdu_buffer, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } size_t length = 45; @@ -286,12 +305,9 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, // if transaction has from field and it is pubkey hash will convert to // address if (tmp_ctx.signing_context.ui.pkhash) { - waves_public_key_hash_to_address( - tmp_ctx.signing_context.ui.line3, - tmp_ctx.signing_context.network_byte, - tmp_ctx.signing_context.ui.line3); + } - if (tmp_ctx.signing_context.data_version > 2) { + if (tmp_ctx.signing_context.message_type == PROTOBUF_DATA) { if (tmp_ctx.signing_context.data_type == 252) { // convert matcher public key to address waves_public_key_to_address(tmp_ctx.signing_context.ui.line2, @@ -418,7 +434,7 @@ static void waves_main(void) { THROW(SW_SECURITY_STATUS_NOT_SATISFIED); } - // PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); + PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); // Call the Apdu handler, handle_apdu(&flags, &tx, rx); diff --git a/src/main.h b/src/main.h index eb2abc4b..c9a192ec 100644 --- a/src/main.h +++ b/src/main.h @@ -38,8 +38,11 @@ #define SW_OK 0x9000 #define SW_USER_CANCELLED 0x9100 #define SW_DEPRECATED_SIGN_PROTOCOL 0x9102 -#define SW_DEVICE_IS_LOCKED 0x6986 +#define SW_INCORRECT_PRECISION_VALUE 0x9103 +#define SW_INCORRECT_TRANSACTION_TYPE_VERSION 0x9104 +#define SW_PROTOBUF_DECODING_FAILED 0x9105 #define SW_CONDITIONS_NOT_SATISFIED 0x6985 +#define SW_DEVICE_IS_LOCKED 0x6986 #define SW_BUFFER_OVERFLOW 0x6990 #define SW_INCORRECT_P1_P2 0x6A86 #define SW_INS_NOT_SUPPORTED 0x6D00 @@ -50,6 +53,9 @@ #define COLOR_APP 0x0055FF #define COLOR_APP_LIGHT 0x87dee6 +#define BYTE_DATA 1 +#define PROTOBUF_DATA 2 + typedef struct internal_storage_t { uint8_t fido_transport; uint8_t initialized; @@ -96,9 +102,9 @@ typedef struct uiContext_t { line3[36]; // reserved for recipient if transaction has recipient message unsigned char line4[45]; unsigned char line5[45]; - unsigned char line6[20]; - unsigned char fee_amount[20]; - unsigned char tmp[20]; + unsigned char line6[22]; + unsigned char fee_amount[22]; + unsigned char tmp[22]; bool pkhash; bool finished; cx_blake2b_t hash_ctx; @@ -116,6 +122,7 @@ typedef struct signingContext_t { unsigned char fee_decimals; unsigned char data_type; unsigned char data_version; + int message_type; unsigned char network_byte; unsigned char signature[64]; unsigned char first_data_hash[45]; diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index d357ab7e..4b06b5ae 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -34,9 +34,13 @@ void inline fetch_new_apdu(uiProtobuf_t *state) void fetch_new_apdu(uiProtobuf_t *state) { unsigned int rx; - G_io_apdu_buffer[0] = 0x90; - G_io_apdu_buffer[1] = 0x00; - rx = io_exchange(CHANNEL_APDU, 2); + unsigned int tx = 0; + unsigned int flags = 0; + unsigned short sw = 0x9000; + G_io_apdu_buffer[tx] = sw >> 8; + G_io_apdu_buffer[tx + 1] = sw; + PRINTF("GET NEW APDU"); + rx = io_exchange(CHANNEL_APDU | flags , 2); if (G_io_apdu_buffer[4] != rx - 5) { // the length of the APDU should match what's in the 5-byte header. // If not fail. Don't want to buffer overrun or anything. @@ -54,7 +58,7 @@ void fetch_new_apdu(uiProtobuf_t *state) { if (tmp_ctx.signing_context.step == 7) { THROW(SW_INCORRECT_P1_P2); } - + PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); state->total_received += G_io_apdu_buffer[4]; } diff --git a/src/nanopb_stubs/amount.pb.c b/src/nanopb_stubs/amount.pb.c index 96e1404a..f93feb70 100644 --- a/src/nanopb_stubs/amount.pb.c +++ b/src/nanopb_stubs/amount.pb.c @@ -7,3 +7,6 @@ #endif PB_BIND(waves_Amount, waves_Amount, AUTO) + + + diff --git a/src/nanopb_stubs/amount.pb.h b/src/nanopb_stubs/amount.pb.h index 78501070..54a4b979 100644 --- a/src/nanopb_stubs/amount.pb.h +++ b/src/nanopb_stubs/amount.pb.h @@ -15,24 +15,23 @@ extern "C" { /* Struct definitions */ typedef struct _waves_Amount { - pb_callback_t asset_id; - int64_t amount; + pb_callback_t asset_id; + int64_t amount; } waves_Amount; + /* Initializer values for message structs */ -#define waves_Amount_init_default \ - { {{NULL}, NULL}, 0 } -#define waves_Amount_init_zero \ - { {{NULL}, NULL}, 0 } +#define waves_Amount_init_default {{{NULL}, NULL}, 0} +#define waves_Amount_init_zero {{{NULL}, NULL}, 0} /* Field tags (for use in manual encoding/decoding) */ -#define waves_Amount_asset_id_tag 1 -#define waves_Amount_amount_tag 2 +#define waves_Amount_asset_id_tag 1 +#define waves_Amount_amount_tag 2 /* Struct field encoding specification for nanopb */ -#define waves_Amount_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ - X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_Amount_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ +X(a, STATIC, SINGULAR, INT64, amount, 2) #define waves_Amount_CALLBACK pb_default_field_callback #define waves_Amount_DEFAULT NULL diff --git a/src/nanopb_stubs/order.pb.c b/src/nanopb_stubs/order.pb.c index 8c48f13d..4c78f576 100644 --- a/src/nanopb_stubs/order.pb.c +++ b/src/nanopb_stubs/order.pb.c @@ -8,4 +8,9 @@ PB_BIND(waves_AssetPair, waves_AssetPair, AUTO) + PB_BIND(waves_Order, waves_Order, AUTO) + + + + diff --git a/src/nanopb_stubs/order.pb.h b/src/nanopb_stubs/order.pb.h index d989c3d5..77128086 100644 --- a/src/nanopb_stubs/order.pb.h +++ b/src/nanopb_stubs/order.pb.h @@ -16,92 +16,79 @@ extern "C" { /* Enum definitions */ typedef enum _waves_Order_Side { - waves_Order_Side_BUY = 0, - waves_Order_Side_SELL = 1 + waves_Order_Side_BUY = 0, + waves_Order_Side_SELL = 1 } waves_Order_Side; /* Struct definitions */ typedef struct _waves_AssetPair { - pb_callback_t amount_asset_id; - pb_callback_t price_asset_id; + pb_callback_t amount_asset_id; + pb_callback_t price_asset_id; } waves_AssetPair; typedef struct _waves_Order { - int32_t chain_id; - pb_callback_t sender_public_key; - pb_callback_t matcher_public_key; - bool has_asset_pair; - waves_AssetPair asset_pair; - waves_Order_Side order_side; - int64_t amount; - int64_t price; - int64_t timestamp; - int64_t expiration; - bool has_matcher_fee; - waves_Amount matcher_fee; - int32_t version; + int32_t chain_id; + pb_callback_t sender_public_key; + pb_callback_t matcher_public_key; + bool has_asset_pair; + waves_AssetPair asset_pair; + waves_Order_Side order_side; + int64_t amount; + int64_t price; + int64_t timestamp; + int64_t expiration; + bool has_matcher_fee; + waves_Amount matcher_fee; + int32_t version; } waves_Order; + /* Helper constants for enums */ #define _waves_Order_Side_MIN waves_Order_Side_BUY #define _waves_Order_Side_MAX waves_Order_Side_SELL -#define _waves_Order_Side_ARRAYSIZE \ - ((waves_Order_Side)(waves_Order_Side_SELL + 1)) +#define _waves_Order_Side_ARRAYSIZE ((waves_Order_Side)(waves_Order_Side_SELL+1)) + /* Initializer values for message structs */ -#define waves_AssetPair_init_default \ - { \ - {{NULL}, NULL}, { {NULL}, NULL } \ - } -#define waves_Order_init_default \ - { \ - 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_default, \ - _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_default, 0 \ - } -#define waves_AssetPair_init_zero \ - { \ - {{NULL}, NULL}, { {NULL}, NULL } \ - } -#define waves_Order_init_zero \ - { \ - 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_zero, \ - _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_zero, 0 \ - } +#define waves_AssetPair_init_default {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_Order_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_default, _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_default, 0} +#define waves_AssetPair_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_Order_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_AssetPair_init_zero, _waves_Order_Side_MIN, 0, 0, 0, 0, false, waves_Amount_init_zero, 0} /* Field tags (for use in manual encoding/decoding) */ -#define waves_AssetPair_amount_asset_id_tag 1 -#define waves_AssetPair_price_asset_id_tag 2 -#define waves_Order_chain_id_tag 1 -#define waves_Order_sender_public_key_tag 2 -#define waves_Order_matcher_public_key_tag 3 -#define waves_Order_asset_pair_tag 4 -#define waves_Order_order_side_tag 5 -#define waves_Order_amount_tag 6 -#define waves_Order_price_tag 7 -#define waves_Order_timestamp_tag 8 -#define waves_Order_expiration_tag 9 -#define waves_Order_matcher_fee_tag 10 -#define waves_Order_version_tag 11 +#define waves_AssetPair_amount_asset_id_tag 1 +#define waves_AssetPair_price_asset_id_tag 2 +#define waves_Order_chain_id_tag 1 +#define waves_Order_sender_public_key_tag 2 +#define waves_Order_matcher_public_key_tag 3 +#define waves_Order_asset_pair_tag 4 +#define waves_Order_order_side_tag 5 +#define waves_Order_amount_tag 6 +#define waves_Order_price_tag 7 +#define waves_Order_timestamp_tag 8 +#define waves_Order_expiration_tag 9 +#define waves_Order_matcher_fee_tag 10 +#define waves_Order_version_tag 11 /* Struct field encoding specification for nanopb */ -#define waves_AssetPair_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, amount_asset_id, 1) \ - X(a, CALLBACK, SINGULAR, BYTES, price_asset_id, 2) +#define waves_AssetPair_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, amount_asset_id, 1) \ +X(a, CALLBACK, SINGULAR, BYTES, price_asset_id, 2) #define waves_AssetPair_CALLBACK pb_default_field_callback #define waves_AssetPair_DEFAULT NULL -#define waves_Order_FIELDLIST(X, a) \ - X(a, STATIC, SINGULAR, INT32, chain_id, 1) \ - X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ - X(a, CALLBACK, SINGULAR, BYTES, matcher_public_key, 3) \ - X(a, STATIC, OPTIONAL, MESSAGE, asset_pair, 4) \ - X(a, STATIC, SINGULAR, UENUM, order_side, 5) \ - X(a, STATIC, SINGULAR, INT64, amount, 6) \ - X(a, STATIC, SINGULAR, INT64, price, 7) \ - X(a, STATIC, SINGULAR, INT64, timestamp, 8) \ - X(a, STATIC, SINGULAR, INT64, expiration, 9) \ - X(a, STATIC, OPTIONAL, MESSAGE, matcher_fee, 10) \ - X(a, STATIC, SINGULAR, INT32, version, 11) +#define waves_Order_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, chain_id, 1) \ +X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ +X(a, CALLBACK, SINGULAR, BYTES, matcher_public_key, 3) \ +X(a, STATIC, OPTIONAL, MESSAGE, asset_pair, 4) \ +X(a, STATIC, SINGULAR, UENUM, order_side, 5) \ +X(a, STATIC, SINGULAR, INT64, amount, 6) \ +X(a, STATIC, SINGULAR, INT64, price, 7) \ +X(a, STATIC, SINGULAR, INT64, timestamp, 8) \ +X(a, STATIC, SINGULAR, INT64, expiration, 9) \ +X(a, STATIC, OPTIONAL, MESSAGE, matcher_fee, 10) \ +X(a, STATIC, SINGULAR, INT32, version, 11) #define waves_Order_CALLBACK pb_default_field_callback #define waves_Order_DEFAULT NULL #define waves_Order_asset_pair_MSGTYPE waves_AssetPair diff --git a/src/nanopb_stubs/recipient.pb.c b/src/nanopb_stubs/recipient.pb.c index 41934730..4ffc8b1d 100644 --- a/src/nanopb_stubs/recipient.pb.c +++ b/src/nanopb_stubs/recipient.pb.c @@ -7,3 +7,6 @@ #endif PB_BIND(waves_Recipient, waves_Recipient, AUTO) + + + diff --git a/src/nanopb_stubs/recipient.pb.h b/src/nanopb_stubs/recipient.pb.h index 34b5a54b..46ca7f94 100644 --- a/src/nanopb_stubs/recipient.pb.h +++ b/src/nanopb_stubs/recipient.pb.h @@ -15,40 +15,27 @@ extern "C" { /* Struct definitions */ typedef struct _waves_Recipient { - pb_size_t which_recipient; - union { - const char *public_key_hash; - const char *alias; - } recipient; + pb_size_t which_recipient; + union { + pb_byte_t public_key_hash[20]; + char alias[30]; + } recipient; } waves_Recipient; + /* Initializer values for message structs */ -#define waves_Recipient_init_default \ - { \ - 0, { \ - { {NULL}, NULL } \ - } \ - } -#define waves_Recipient_init_zero \ - { \ - 0, { \ - { {NULL}, NULL } \ - } \ - } +#define waves_Recipient_init_default {0, {{0}}} +#define waves_Recipient_init_zero {0, {{0}}} /* Field tags (for use in manual encoding/decoding) */ -#define waves_Recipient_public_key_hash_tag 1 -#define waves_Recipient_alias_tag 2 +#define waves_Recipient_public_key_hash_tag 1 +#define waves_Recipient_alias_tag 2 /* Struct field encoding specification for nanopb */ -#define waves_Recipient_FIELDLIST(X, a) \ - X(a, CALLBACK, ONEOF, BYTES, \ - (recipient, public_key_hash, recipient.public_key_hash), 1) \ - X(a, CALLBACK, ONEOF, STRING, (recipient, alias, recipient.alias), 2) -extern bool waves_Recipient_callback(pb_istream_t *istream, - pb_ostream_t *ostream, - const pb_field_t *field); -#define waves_Recipient_CALLBACK waves_Recipient_callback +#define waves_Recipient_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, FIXED_LENGTH_BYTES, (recipient,public_key_hash,recipient.public_key_hash), 1) \ +X(a, STATIC, ONEOF, STRING, (recipient,alias,recipient.alias), 2) +#define waves_Recipient_CALLBACK NULL #define waves_Recipient_DEFAULT NULL extern const pb_msgdesc_t waves_Recipient_msg; @@ -57,7 +44,7 @@ extern const pb_msgdesc_t waves_Recipient_msg; #define waves_Recipient_fields &waves_Recipient_msg /* Maximum encoded size of messages (where known) */ -/* waves_Recipient_size depends on runtime parameters */ +#define waves_Recipient_size 31 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/nanopb_stubs/transaction.pb.c b/src/nanopb_stubs/transaction.pb.c index 96322c81..ed73bb56 100644 --- a/src/nanopb_stubs/transaction.pb.c +++ b/src/nanopb_stubs/transaction.pb.c @@ -8,47 +8,59 @@ PB_BIND(waves_SignedTransaction, waves_SignedTransaction, AUTO) + PB_BIND(waves_Transaction, waves_Transaction, 2) + PB_BIND(waves_GenesisTransactionData, waves_GenesisTransactionData, AUTO) + PB_BIND(waves_PaymentTransactionData, waves_PaymentTransactionData, AUTO) + PB_BIND(waves_TransferTransactionData, waves_TransferTransactionData, AUTO) -PB_BIND(waves_CreateAliasTransactionData, waves_CreateAliasTransactionData, - AUTO) + +PB_BIND(waves_CreateAliasTransactionData, waves_CreateAliasTransactionData, AUTO) + PB_BIND(waves_DataTransactionData, waves_DataTransactionData, AUTO) -PB_BIND(waves_DataTransactionData_DataEntry, - waves_DataTransactionData_DataEntry, AUTO) -PB_BIND(waves_MassTransferTransactionData, waves_MassTransferTransactionData, - AUTO) +PB_BIND(waves_MassTransferTransactionData, waves_MassTransferTransactionData, AUTO) + PB_BIND(waves_LeaseTransactionData, waves_LeaseTransactionData, AUTO) -PB_BIND(waves_LeaseCancelTransactionData, waves_LeaseCancelTransactionData, - AUTO) + +PB_BIND(waves_LeaseCancelTransactionData, waves_LeaseCancelTransactionData, AUTO) + PB_BIND(waves_BurnTransactionData, waves_BurnTransactionData, AUTO) + PB_BIND(waves_IssueTransactionData, waves_IssueTransactionData, AUTO) + PB_BIND(waves_ReissueTransactionData, waves_ReissueTransactionData, AUTO) -PB_BIND(waves_SetAssetScriptTransactionData, - waves_SetAssetScriptTransactionData, AUTO) + +PB_BIND(waves_SetAssetScriptTransactionData, waves_SetAssetScriptTransactionData, AUTO) + PB_BIND(waves_SetScriptTransactionData, waves_SetScriptTransactionData, AUTO) + PB_BIND(waves_ExchangeTransactionData, waves_ExchangeTransactionData, AUTO) + PB_BIND(waves_SponsorFeeTransactionData, waves_SponsorFeeTransactionData, AUTO) -PB_BIND(waves_InvokeScriptTransactionData, waves_InvokeScriptTransactionData, - AUTO) -PB_BIND(waves_UpdateAssetInfoTransactionData, - waves_UpdateAssetInfoTransactionData, AUTO) +PB_BIND(waves_InvokeScriptTransactionData, waves_InvokeScriptTransactionData, AUTO) + + +PB_BIND(waves_UpdateAssetInfoTransactionData, waves_UpdateAssetInfoTransactionData, AUTO) + + + diff --git a/src/nanopb_stubs/transaction.pb.h b/src/nanopb_stubs/transaction.pb.h index 9aa8fc62..c25c86a9 100644 --- a/src/nanopb_stubs/transaction.pb.h +++ b/src/nanopb_stubs/transaction.pb.h @@ -18,276 +18,168 @@ extern "C" { /* Struct definitions */ typedef struct _waves_CreateAliasTransactionData { - pb_callback_t alias; + pb_callback_t alias; } waves_CreateAliasTransactionData; typedef struct _waves_DataTransactionData { - char dummy_field; + char dummy_field; } waves_DataTransactionData; -typedef struct _waves_DataTransactionData_DataEntry { - char dummy_field; -} waves_DataTransactionData_DataEntry; +typedef struct _waves_ExchangeTransactionData { + char dummy_field; +} waves_ExchangeTransactionData; + +typedef struct _waves_GenesisTransactionData { + char dummy_field; +} waves_GenesisTransactionData; typedef struct _waves_LeaseCancelTransactionData { - pb_callback_t lease_id; + pb_callback_t lease_id; } waves_LeaseCancelTransactionData; typedef struct _waves_MassTransferTransactionData { - pb_callback_t asset_id; - pb_callback_t attachment; + pb_callback_t asset_id; + pb_callback_t attachment; } waves_MassTransferTransactionData; +typedef struct _waves_PaymentTransactionData { + char dummy_field; +} waves_PaymentTransactionData; + typedef struct _waves_SetAssetScriptTransactionData { - pb_callback_t asset_id; + pb_callback_t asset_id; } waves_SetAssetScriptTransactionData; typedef struct _waves_SetScriptTransactionData { - char dummy_field; + char dummy_field; } waves_SetScriptTransactionData; typedef struct _waves_UpdateAssetInfoTransactionData { - pb_callback_t asset_id; - pb_callback_t name; - pb_callback_t description; + pb_callback_t asset_id; + pb_callback_t name; + pb_callback_t description; } waves_UpdateAssetInfoTransactionData; typedef struct _waves_BurnTransactionData { - bool has_asset_amount; - waves_Amount asset_amount; + bool has_asset_amount; + waves_Amount asset_amount; } waves_BurnTransactionData; -typedef struct _waves_ExchangeTransactionData { - int64_t amount; - int64_t price; - int64_t buy_matcher_fee; - int64_t sell_matcher_fee; - pb_callback_t orders; -} waves_ExchangeTransactionData; - -typedef struct _waves_GenesisTransactionData { - pb_callback_t recipient_address; - int64_t amount; -} waves_GenesisTransactionData; - typedef struct _waves_InvokeScriptTransactionData { - bool has_d_app; - waves_Recipient d_app; - pb_callback_t function_call; - pb_size_t payments_count; - waves_Amount payments[2]; + bool has_d_app; + waves_Recipient d_app; + pb_callback_t function_call; + pb_size_t payments_count; + waves_Amount payments[2]; } waves_InvokeScriptTransactionData; typedef struct _waves_IssueTransactionData { - pb_callback_t name; - pb_callback_t description; - int64_t amount; - int32_t decimals; - bool reissuable; + pb_callback_t name; + pb_callback_t description; + int64_t amount; + int32_t decimals; + bool reissuable; } waves_IssueTransactionData; typedef struct _waves_LeaseTransactionData { - bool has_recipient; - waves_Recipient recipient; - int64_t amount; + bool has_recipient; + waves_Recipient recipient; + int64_t amount; } waves_LeaseTransactionData; -typedef struct _waves_PaymentTransactionData { - pb_callback_t recipient_address; - int64_t amount; -} waves_PaymentTransactionData; - typedef struct _waves_ReissueTransactionData { - bool has_asset_amount; - waves_Amount asset_amount; - bool reissuable; + bool has_asset_amount; + waves_Amount asset_amount; + bool reissuable; } waves_ReissueTransactionData; typedef struct _waves_SponsorFeeTransactionData { - bool has_min_fee; - waves_Amount min_fee; + bool has_min_fee; + waves_Amount min_fee; } waves_SponsorFeeTransactionData; typedef struct _waves_TransferTransactionData { - bool has_recipient; - waves_Recipient recipient; - bool has_amount; - waves_Amount amount; - pb_callback_t attachment; + bool has_recipient; + waves_Recipient recipient; + bool has_amount; + waves_Amount amount; + pb_callback_t attachment; } waves_TransferTransactionData; typedef struct _waves_Transaction { - int32_t chain_id; - pb_callback_t sender_public_key; - pb_callback_t cb_fee; - bool has_fee; - waves_Amount fee; - int64_t timestamp; - int32_t version; - pb_callback_t cb_data; - pb_size_t which_data; - union { - waves_GenesisTransactionData genesis; - waves_PaymentTransactionData payment; - waves_IssueTransactionData issue; - waves_TransferTransactionData transfer; - waves_ReissueTransactionData reissue; - waves_BurnTransactionData burn; - waves_ExchangeTransactionData exchange; - waves_LeaseTransactionData lease; - waves_LeaseCancelTransactionData lease_cancel; - waves_CreateAliasTransactionData create_alias; - waves_MassTransferTransactionData mass_transfer; - waves_DataTransactionData data_transaction; - waves_SetScriptTransactionData set_script; - waves_SponsorFeeTransactionData sponsor_fee; - waves_SetAssetScriptTransactionData set_asset_script; - waves_InvokeScriptTransactionData invoke_script; - waves_UpdateAssetInfoTransactionData update_asset_info; - } data; + pb_callback_t sender_public_key; + pb_callback_t cb_fee; + bool has_fee; + waves_Amount fee; + pb_callback_t cb_data; + pb_size_t which_data; + union { + waves_GenesisTransactionData genesis; + waves_PaymentTransactionData payment; + waves_IssueTransactionData issue; + waves_TransferTransactionData transfer; + waves_ReissueTransactionData reissue; + waves_BurnTransactionData burn; + waves_ExchangeTransactionData exchange; + waves_LeaseTransactionData lease; + waves_LeaseCancelTransactionData lease_cancel; + waves_CreateAliasTransactionData create_alias; + waves_MassTransferTransactionData mass_transfer; + waves_DataTransactionData data_transaction; + waves_SetScriptTransactionData set_script; + waves_SponsorFeeTransactionData sponsor_fee; + waves_SetAssetScriptTransactionData set_asset_script; + waves_InvokeScriptTransactionData invoke_script; + waves_UpdateAssetInfoTransactionData update_asset_info; + } data; } waves_Transaction; typedef struct _waves_SignedTransaction { - bool has_transaction; - waves_Transaction transaction; - pb_callback_t proofs; + bool has_transaction; + waves_Transaction transaction; + pb_callback_t proofs; } waves_SignedTransaction; + /* Initializer values for message structs */ -#define waves_SignedTransaction_init_default \ - { \ - false, waves_Transaction_init_default, { {NULL}, NULL } \ - } -#define waves_Transaction_init_default \ - { \ - 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_default, 0, 0, \ - {{NULL}, NULL}, 0, { \ - waves_GenesisTransactionData_init_default \ - } \ - } -#define waves_GenesisTransactionData_init_default \ - { {{NULL}, NULL}, 0 } -#define waves_PaymentTransactionData_init_default \ - { {{NULL}, NULL}, 0 } -#define waves_TransferTransactionData_init_default \ - { \ - false, waves_Recipient_init_default, false, waves_Amount_init_default, { \ - {NULL}, NULL \ - } \ - } -#define waves_CreateAliasTransactionData_init_default \ - { \ - { {NULL}, NULL } \ - } -#define waves_DataTransactionData_init_default \ - { 0 } -#define waves_DataTransactionData_DataEntry_init_default \ - { 0 } -#define waves_MassTransferTransactionData_init_default \ - { \ - {{NULL}, NULL}, { {NULL}, NULL } \ - } -#define waves_LeaseTransactionData_init_default \ - { false, waves_Recipient_init_default, 0 } -#define waves_LeaseCancelTransactionData_init_default \ - { \ - { {NULL}, NULL } \ - } -#define waves_BurnTransactionData_init_default \ - { false, waves_Amount_init_default } -#define waves_IssueTransactionData_init_default \ - { {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0 } -#define waves_ReissueTransactionData_init_default \ - { false, waves_Amount_init_default, 0 } -#define waves_SetAssetScriptTransactionData_init_default \ - { \ - { {NULL}, NULL } \ - } -#define waves_SetScriptTransactionData_init_default \ - { 0 } -#define waves_ExchangeTransactionData_init_default \ - { \ - 0, 0, 0, 0, { {NULL}, NULL } \ - } -#define waves_SponsorFeeTransactionData_init_default \ - { false, waves_Amount_init_default } -#define waves_InvokeScriptTransactionData_init_default \ - { \ - false, waves_Recipient_init_default, {{NULL}, NULL}, 0, { \ - waves_Amount_init_default, waves_Amount_init_default \ - } \ - } -#define waves_UpdateAssetInfoTransactionData_init_default \ - { \ - {{NULL}, NULL}, {{NULL}, NULL}, { {NULL}, NULL } \ - } -#define waves_SignedTransaction_init_zero \ - { \ - false, waves_Transaction_init_zero, { {NULL}, NULL } \ - } -#define waves_Transaction_init_zero \ - { \ - 0, {{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_zero, 0, 0, \ - {{NULL}, NULL}, 0, { \ - waves_GenesisTransactionData_init_zero \ - } \ - } -#define waves_GenesisTransactionData_init_zero \ - { {{NULL}, NULL}, 0 } -#define waves_PaymentTransactionData_init_zero \ - { {{NULL}, NULL}, 0 } -#define waves_TransferTransactionData_init_zero \ - { \ - false, waves_Recipient_init_zero, false, waves_Amount_init_zero, { \ - {NULL}, NULL \ - } \ - } -#define waves_CreateAliasTransactionData_init_zero \ - { \ - { {NULL}, NULL } \ - } -#define waves_DataTransactionData_init_zero \ - { 0 } -#define waves_DataTransactionData_DataEntry_init_zero \ - { 0 } -#define waves_MassTransferTransactionData_init_zero \ - { \ - {{NULL}, NULL}, { {NULL}, NULL } \ - } -#define waves_LeaseTransactionData_init_zero \ - { false, waves_Recipient_init_zero, 0 } -#define waves_LeaseCancelTransactionData_init_zero \ - { \ - { {NULL}, NULL } \ - } -#define waves_BurnTransactionData_init_zero \ - { false, waves_Amount_init_zero } -#define waves_IssueTransactionData_init_zero \ - { {{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0 } -#define waves_ReissueTransactionData_init_zero \ - { false, waves_Amount_init_zero, 0 } -#define waves_SetAssetScriptTransactionData_init_zero \ - { \ - { {NULL}, NULL } \ - } -#define waves_SetScriptTransactionData_init_zero \ - { 0 } -#define waves_ExchangeTransactionData_init_zero \ - { \ - 0, 0, 0, 0, { {NULL}, NULL } \ - } -#define waves_SponsorFeeTransactionData_init_zero \ - { false, waves_Amount_init_zero } -#define waves_InvokeScriptTransactionData_init_zero \ - { \ - false, waves_Recipient_init_zero, {{NULL}, NULL}, 0, { \ - waves_Amount_init_zero, waves_Amount_init_zero \ - } \ - } -#define waves_UpdateAssetInfoTransactionData_init_zero \ - { \ - {{NULL}, NULL}, {{NULL}, NULL}, { {NULL}, NULL } \ - } +#define waves_SignedTransaction_init_default {false, waves_Transaction_init_default, {{NULL}, NULL}} +#define waves_Transaction_init_default {{{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_default, {{NULL}, NULL}, 0, {waves_GenesisTransactionData_init_default}} +#define waves_GenesisTransactionData_init_default {0} +#define waves_PaymentTransactionData_init_default {0} +#define waves_TransferTransactionData_init_default {false, waves_Recipient_init_default, false, waves_Amount_init_default, {{NULL}, NULL}} +#define waves_CreateAliasTransactionData_init_default {{{NULL}, NULL}} +#define waves_DataTransactionData_init_default {0} +#define waves_MassTransferTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_LeaseTransactionData_init_default {false, waves_Recipient_init_default, 0} +#define waves_LeaseCancelTransactionData_init_default {{{NULL}, NULL}} +#define waves_BurnTransactionData_init_default {false, waves_Amount_init_default} +#define waves_IssueTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0} +#define waves_ReissueTransactionData_init_default {false, waves_Amount_init_default, 0} +#define waves_SetAssetScriptTransactionData_init_default {{{NULL}, NULL}} +#define waves_SetScriptTransactionData_init_default {0} +#define waves_ExchangeTransactionData_init_default {0} +#define waves_SponsorFeeTransactionData_init_default {false, waves_Amount_init_default} +#define waves_InvokeScriptTransactionData_init_default {false, waves_Recipient_init_default, {{NULL}, NULL}, 0, {waves_Amount_init_default, waves_Amount_init_default}} +#define waves_UpdateAssetInfoTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} +#define waves_SignedTransaction_init_zero {false, waves_Transaction_init_zero, {{NULL}, NULL}} +#define waves_Transaction_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, false, waves_Amount_init_zero, {{NULL}, NULL}, 0, {waves_GenesisTransactionData_init_zero}} +#define waves_GenesisTransactionData_init_zero {0} +#define waves_PaymentTransactionData_init_zero {0} +#define waves_TransferTransactionData_init_zero {false, waves_Recipient_init_zero, false, waves_Amount_init_zero, {{NULL}, NULL}} +#define waves_CreateAliasTransactionData_init_zero {{{NULL}, NULL}} +#define waves_DataTransactionData_init_zero {0} +#define waves_MassTransferTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} +#define waves_LeaseTransactionData_init_zero {false, waves_Recipient_init_zero, 0} +#define waves_LeaseCancelTransactionData_init_zero {{{NULL}, NULL}} +#define waves_BurnTransactionData_init_zero {false, waves_Amount_init_zero} +#define waves_IssueTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0} +#define waves_ReissueTransactionData_init_zero {false, waves_Amount_init_zero, 0} +#define waves_SetAssetScriptTransactionData_init_zero {{{NULL}, NULL}} +#define waves_SetScriptTransactionData_init_zero {0} +#define waves_ExchangeTransactionData_init_zero {0} +#define waves_SponsorFeeTransactionData_init_zero {false, waves_Amount_init_zero} +#define waves_InvokeScriptTransactionData_init_zero {false, waves_Recipient_init_zero, {{NULL}, NULL}, 0, {waves_Amount_init_zero, waves_Amount_init_zero}} +#define waves_UpdateAssetInfoTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}} /* Field tags (for use in manual encoding/decoding) */ #define waves_CreateAliasTransactionData_alias_tag 1 @@ -299,92 +191,72 @@ typedef struct _waves_SignedTransaction { #define waves_UpdateAssetInfoTransactionData_name_tag 2 #define waves_UpdateAssetInfoTransactionData_description_tag 3 #define waves_BurnTransactionData_asset_amount_tag 1 -#define waves_ExchangeTransactionData_amount_tag 1 -#define waves_ExchangeTransactionData_price_tag 2 -#define waves_ExchangeTransactionData_buy_matcher_fee_tag 3 -#define waves_ExchangeTransactionData_sell_matcher_fee_tag 4 -#define waves_ExchangeTransactionData_orders_tag 5 -#define waves_GenesisTransactionData_recipient_address_tag 1 -#define waves_GenesisTransactionData_amount_tag 2 #define waves_InvokeScriptTransactionData_d_app_tag 1 #define waves_InvokeScriptTransactionData_function_call_tag 2 #define waves_InvokeScriptTransactionData_payments_tag 3 -#define waves_IssueTransactionData_name_tag 1 +#define waves_IssueTransactionData_name_tag 1 #define waves_IssueTransactionData_description_tag 2 -#define waves_IssueTransactionData_amount_tag 3 -#define waves_IssueTransactionData_decimals_tag 4 +#define waves_IssueTransactionData_amount_tag 3 +#define waves_IssueTransactionData_decimals_tag 4 #define waves_IssueTransactionData_reissuable_tag 5 #define waves_LeaseTransactionData_recipient_tag 1 -#define waves_LeaseTransactionData_amount_tag 2 -#define waves_PaymentTransactionData_recipient_address_tag 1 -#define waves_PaymentTransactionData_amount_tag 2 +#define waves_LeaseTransactionData_amount_tag 2 #define waves_ReissueTransactionData_asset_amount_tag 1 #define waves_ReissueTransactionData_reissuable_tag 2 #define waves_SponsorFeeTransactionData_min_fee_tag 1 #define waves_TransferTransactionData_recipient_tag 1 #define waves_TransferTransactionData_amount_tag 2 #define waves_TransferTransactionData_attachment_tag 3 -#define waves_Transaction_genesis_tag 101 -#define waves_Transaction_payment_tag 102 -#define waves_Transaction_issue_tag 103 -#define waves_Transaction_transfer_tag 104 -#define waves_Transaction_reissue_tag 105 -#define waves_Transaction_burn_tag 106 -#define waves_Transaction_exchange_tag 107 -#define waves_Transaction_lease_tag 108 -#define waves_Transaction_lease_cancel_tag 109 -#define waves_Transaction_create_alias_tag 110 -#define waves_Transaction_mass_transfer_tag 111 -#define waves_Transaction_data_transaction_tag 112 -#define waves_Transaction_set_script_tag 113 -#define waves_Transaction_sponsor_fee_tag 114 -#define waves_Transaction_set_asset_script_tag 115 -#define waves_Transaction_invoke_script_tag 116 -#define waves_Transaction_update_asset_info_tag 117 -#define waves_Transaction_chain_id_tag 1 -#define waves_Transaction_sender_public_key_tag 2 -#define waves_Transaction_fee_tag 3 -#define waves_Transaction_timestamp_tag 4 -#define waves_Transaction_version_tag 5 -#define waves_SignedTransaction_transaction_tag 1 -#define waves_SignedTransaction_proofs_tag 2 +#define waves_Transaction_genesis_tag 101 +#define waves_Transaction_payment_tag 102 +#define waves_Transaction_issue_tag 103 +#define waves_Transaction_transfer_tag 104 +#define waves_Transaction_reissue_tag 105 +#define waves_Transaction_burn_tag 106 +#define waves_Transaction_exchange_tag 107 +#define waves_Transaction_lease_tag 108 +#define waves_Transaction_lease_cancel_tag 109 +#define waves_Transaction_create_alias_tag 110 +#define waves_Transaction_mass_transfer_tag 111 +#define waves_Transaction_data_transaction_tag 112 +#define waves_Transaction_set_script_tag 113 +#define waves_Transaction_sponsor_fee_tag 114 +#define waves_Transaction_set_asset_script_tag 115 +#define waves_Transaction_invoke_script_tag 116 +#define waves_Transaction_update_asset_info_tag 117 +#define waves_Transaction_sender_public_key_tag 2 +#define waves_Transaction_fee_tag 3 +#define waves_SignedTransaction_transaction_tag 1 +#define waves_SignedTransaction_proofs_tag 2 /* Struct field encoding specification for nanopb */ -#define waves_SignedTransaction_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, transaction, 1) \ - X(a, CALLBACK, REPEATED, BYTES, proofs, 2) +#define waves_SignedTransaction_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, transaction, 1) \ +X(a, CALLBACK, REPEATED, BYTES, proofs, 2) #define waves_SignedTransaction_CALLBACK pb_default_field_callback #define waves_SignedTransaction_DEFAULT NULL #define waves_SignedTransaction_transaction_MSGTYPE waves_Transaction -#define waves_Transaction_FIELDLIST(X, a) \ - X(a, STATIC, SINGULAR, INT32, chain_id, 1) \ - X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ - X(a, STATIC, OPTIONAL, MSG_W_CB, fee, 3) \ - X(a, STATIC, SINGULAR, INT64, timestamp, 4) \ - X(a, STATIC, SINGULAR, INT32, version, 5) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, genesis, data.genesis), 101) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, payment, data.payment), 102) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, issue, data.issue), 103) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, transfer, data.transfer), 104) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, reissue, data.reissue), 105) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, burn, data.burn), 106) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, exchange, data.exchange), 107) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, lease, data.lease), 108) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, lease_cancel, data.lease_cancel), 109) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, create_alias, data.create_alias), 110) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, mass_transfer, data.mass_transfer), \ - 111) \ - X(a, STATIC, ONEOF, MSG_W_CB, \ - (data, data_transaction, data.data_transaction), 112) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, set_script, data.set_script), 113) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, sponsor_fee, data.sponsor_fee), 114) \ - X(a, STATIC, ONEOF, MSG_W_CB, \ - (data, set_asset_script, data.set_asset_script), 115) \ - X(a, STATIC, ONEOF, MSG_W_CB, (data, invoke_script, data.invoke_script), \ - 116) \ - X(a, STATIC, ONEOF, MSG_W_CB, \ - (data, update_asset_info, data.update_asset_info), 117) +#define waves_Transaction_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, sender_public_key, 2) \ +X(a, STATIC, OPTIONAL, MSG_W_CB, fee, 3) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,genesis,data.genesis), 101) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,payment,data.payment), 102) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,issue,data.issue), 103) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,transfer,data.transfer), 104) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,reissue,data.reissue), 105) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,burn,data.burn), 106) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,exchange,data.exchange), 107) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,lease,data.lease), 108) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,lease_cancel,data.lease_cancel), 109) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,create_alias,data.create_alias), 110) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,mass_transfer,data.mass_transfer), 111) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,data_transaction,data.data_transaction), 112) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,set_script,data.set_script), 113) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,sponsor_fee,data.sponsor_fee), 114) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,set_asset_script,data.set_asset_script), 115) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,invoke_script,data.invoke_script), 116) \ +X(a, STATIC, ONEOF, MSG_W_CB, (data,update_asset_info,data.update_asset_info), 117) #define waves_Transaction_CALLBACK pb_default_field_callback #define waves_Transaction_DEFAULT NULL #define waves_Transaction_fee_MSGTYPE waves_Amount @@ -396,139 +268,119 @@ typedef struct _waves_SignedTransaction { #define waves_Transaction_data_burn_MSGTYPE waves_BurnTransactionData #define waves_Transaction_data_exchange_MSGTYPE waves_ExchangeTransactionData #define waves_Transaction_data_lease_MSGTYPE waves_LeaseTransactionData -#define waves_Transaction_data_lease_cancel_MSGTYPE \ - waves_LeaseCancelTransactionData -#define waves_Transaction_data_create_alias_MSGTYPE \ - waves_CreateAliasTransactionData -#define waves_Transaction_data_mass_transfer_MSGTYPE \ - waves_MassTransferTransactionData -#define waves_Transaction_data_data_transaction_MSGTYPE \ - waves_DataTransactionData +#define waves_Transaction_data_lease_cancel_MSGTYPE waves_LeaseCancelTransactionData +#define waves_Transaction_data_create_alias_MSGTYPE waves_CreateAliasTransactionData +#define waves_Transaction_data_mass_transfer_MSGTYPE waves_MassTransferTransactionData +#define waves_Transaction_data_data_transaction_MSGTYPE waves_DataTransactionData #define waves_Transaction_data_set_script_MSGTYPE waves_SetScriptTransactionData -#define waves_Transaction_data_sponsor_fee_MSGTYPE \ - waves_SponsorFeeTransactionData -#define waves_Transaction_data_set_asset_script_MSGTYPE \ - waves_SetAssetScriptTransactionData -#define waves_Transaction_data_invoke_script_MSGTYPE \ - waves_InvokeScriptTransactionData -#define waves_Transaction_data_update_asset_info_MSGTYPE \ - waves_UpdateAssetInfoTransactionData - -#define waves_GenesisTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, recipient_address, 1) \ - X(a, STATIC, SINGULAR, INT64, amount, 2) -#define waves_GenesisTransactionData_CALLBACK pb_default_field_callback +#define waves_Transaction_data_sponsor_fee_MSGTYPE waves_SponsorFeeTransactionData +#define waves_Transaction_data_set_asset_script_MSGTYPE waves_SetAssetScriptTransactionData +#define waves_Transaction_data_invoke_script_MSGTYPE waves_InvokeScriptTransactionData +#define waves_Transaction_data_update_asset_info_MSGTYPE waves_UpdateAssetInfoTransactionData + +#define waves_GenesisTransactionData_FIELDLIST(X, a) \ + +#define waves_GenesisTransactionData_CALLBACK NULL #define waves_GenesisTransactionData_DEFAULT NULL -#define waves_PaymentTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, recipient_address, 1) \ - X(a, STATIC, SINGULAR, INT64, amount, 2) -#define waves_PaymentTransactionData_CALLBACK pb_default_field_callback +#define waves_PaymentTransactionData_FIELDLIST(X, a) \ + +#define waves_PaymentTransactionData_CALLBACK NULL #define waves_PaymentTransactionData_DEFAULT NULL -#define waves_TransferTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ - X(a, STATIC, OPTIONAL, MESSAGE, amount, 2) \ - X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) +#define waves_TransferTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, amount, 2) \ +X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) #define waves_TransferTransactionData_CALLBACK pb_default_field_callback #define waves_TransferTransactionData_DEFAULT NULL #define waves_TransferTransactionData_recipient_MSGTYPE waves_Recipient #define waves_TransferTransactionData_amount_MSGTYPE waves_Amount -#define waves_CreateAliasTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, STRING, alias, 1) +#define waves_CreateAliasTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, STRING, alias, 1) #define waves_CreateAliasTransactionData_CALLBACK pb_default_field_callback #define waves_CreateAliasTransactionData_DEFAULT NULL -#define waves_DataTransactionData_FIELDLIST(X, a) +#define waves_DataTransactionData_FIELDLIST(X, a) \ #define waves_DataTransactionData_CALLBACK NULL #define waves_DataTransactionData_DEFAULT NULL -#define waves_DataTransactionData_DataEntry_FIELDLIST(X, a) - -#define waves_DataTransactionData_DataEntry_CALLBACK NULL -#define waves_DataTransactionData_DataEntry_DEFAULT NULL - -#define waves_MassTransferTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ - X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) +#define waves_MassTransferTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ +X(a, CALLBACK, SINGULAR, BYTES, attachment, 3) #define waves_MassTransferTransactionData_CALLBACK pb_default_field_callback #define waves_MassTransferTransactionData_DEFAULT NULL -#define waves_LeaseTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ - X(a, STATIC, SINGULAR, INT64, amount, 2) +#define waves_LeaseTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, recipient, 1) \ +X(a, STATIC, SINGULAR, INT64, amount, 2) #define waves_LeaseTransactionData_CALLBACK NULL #define waves_LeaseTransactionData_DEFAULT NULL #define waves_LeaseTransactionData_recipient_MSGTYPE waves_Recipient -#define waves_LeaseCancelTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, lease_id, 1) +#define waves_LeaseCancelTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, lease_id, 1) #define waves_LeaseCancelTransactionData_CALLBACK pb_default_field_callback #define waves_LeaseCancelTransactionData_DEFAULT NULL -#define waves_BurnTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) +#define waves_BurnTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) #define waves_BurnTransactionData_CALLBACK NULL #define waves_BurnTransactionData_DEFAULT NULL #define waves_BurnTransactionData_asset_amount_MSGTYPE waves_Amount -#define waves_IssueTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, STRING, name, 1) \ - X(a, CALLBACK, SINGULAR, STRING, description, 2) \ - X(a, STATIC, SINGULAR, INT64, amount, 3) \ - X(a, STATIC, SINGULAR, INT32, decimals, 4) \ - X(a, STATIC, SINGULAR, BOOL, reissuable, 5) +#define waves_IssueTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, STRING, name, 1) \ +X(a, CALLBACK, SINGULAR, STRING, description, 2) \ +X(a, STATIC, SINGULAR, INT64, amount, 3) \ +X(a, STATIC, SINGULAR, INT32, decimals, 4) \ +X(a, STATIC, SINGULAR, BOOL, reissuable, 5) #define waves_IssueTransactionData_CALLBACK pb_default_field_callback #define waves_IssueTransactionData_DEFAULT NULL -#define waves_ReissueTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) \ - X(a, STATIC, SINGULAR, BOOL, reissuable, 2) +#define waves_ReissueTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, asset_amount, 1) \ +X(a, STATIC, SINGULAR, BOOL, reissuable, 2) #define waves_ReissueTransactionData_CALLBACK NULL #define waves_ReissueTransactionData_DEFAULT NULL #define waves_ReissueTransactionData_asset_amount_MSGTYPE waves_Amount -#define waves_SetAssetScriptTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) +#define waves_SetAssetScriptTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) #define waves_SetAssetScriptTransactionData_CALLBACK pb_default_field_callback #define waves_SetAssetScriptTransactionData_DEFAULT NULL -#define waves_SetScriptTransactionData_FIELDLIST(X, a) +#define waves_SetScriptTransactionData_FIELDLIST(X, a) \ #define waves_SetScriptTransactionData_CALLBACK NULL #define waves_SetScriptTransactionData_DEFAULT NULL -#define waves_ExchangeTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, SINGULAR, INT64, amount, 1) \ - X(a, STATIC, SINGULAR, INT64, price, 2) \ - X(a, STATIC, SINGULAR, INT64, buy_matcher_fee, 3) \ - X(a, STATIC, SINGULAR, INT64, sell_matcher_fee, 4) \ - X(a, CALLBACK, REPEATED, MESSAGE, orders, 5) -#define waves_ExchangeTransactionData_CALLBACK pb_default_field_callback +#define waves_ExchangeTransactionData_FIELDLIST(X, a) \ + +#define waves_ExchangeTransactionData_CALLBACK NULL #define waves_ExchangeTransactionData_DEFAULT NULL -#define waves_ExchangeTransactionData_orders_MSGTYPE waves_Order -#define waves_SponsorFeeTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, min_fee, 1) +#define waves_SponsorFeeTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, min_fee, 1) #define waves_SponsorFeeTransactionData_CALLBACK NULL #define waves_SponsorFeeTransactionData_DEFAULT NULL #define waves_SponsorFeeTransactionData_min_fee_MSGTYPE waves_Amount -#define waves_InvokeScriptTransactionData_FIELDLIST(X, a) \ - X(a, STATIC, OPTIONAL, MESSAGE, d_app, 1) \ - X(a, CALLBACK, SINGULAR, BYTES, function_call, 2) \ - X(a, STATIC, REPEATED, MESSAGE, payments, 3) +#define waves_InvokeScriptTransactionData_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, d_app, 1) \ +X(a, CALLBACK, SINGULAR, BYTES, function_call, 2) \ +X(a, STATIC, REPEATED, MESSAGE, payments, 3) #define waves_InvokeScriptTransactionData_CALLBACK pb_default_field_callback #define waves_InvokeScriptTransactionData_DEFAULT NULL #define waves_InvokeScriptTransactionData_d_app_MSGTYPE waves_Recipient #define waves_InvokeScriptTransactionData_payments_MSGTYPE waves_Amount -#define waves_UpdateAssetInfoTransactionData_FIELDLIST(X, a) \ - X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ - X(a, CALLBACK, SINGULAR, STRING, name, 2) \ - X(a, CALLBACK, SINGULAR, STRING, description, 3) +#define waves_UpdateAssetInfoTransactionData_FIELDLIST(X, a) \ +X(a, CALLBACK, SINGULAR, BYTES, asset_id, 1) \ +X(a, CALLBACK, SINGULAR, STRING, name, 2) \ +X(a, CALLBACK, SINGULAR, STRING, description, 3) #define waves_UpdateAssetInfoTransactionData_CALLBACK pb_default_field_callback #define waves_UpdateAssetInfoTransactionData_DEFAULT NULL @@ -539,7 +391,6 @@ extern const pb_msgdesc_t waves_PaymentTransactionData_msg; extern const pb_msgdesc_t waves_TransferTransactionData_msg; extern const pb_msgdesc_t waves_CreateAliasTransactionData_msg; extern const pb_msgdesc_t waves_DataTransactionData_msg; -extern const pb_msgdesc_t waves_DataTransactionData_DataEntry_msg; extern const pb_msgdesc_t waves_MassTransferTransactionData_msg; extern const pb_msgdesc_t waves_LeaseTransactionData_msg; extern const pb_msgdesc_t waves_LeaseCancelTransactionData_msg; @@ -559,50 +410,39 @@ extern const pb_msgdesc_t waves_UpdateAssetInfoTransactionData_msg; #define waves_GenesisTransactionData_fields &waves_GenesisTransactionData_msg #define waves_PaymentTransactionData_fields &waves_PaymentTransactionData_msg #define waves_TransferTransactionData_fields &waves_TransferTransactionData_msg -#define waves_CreateAliasTransactionData_fields \ - &waves_CreateAliasTransactionData_msg +#define waves_CreateAliasTransactionData_fields &waves_CreateAliasTransactionData_msg #define waves_DataTransactionData_fields &waves_DataTransactionData_msg -#define waves_DataTransactionData_DataEntry_fields \ - &waves_DataTransactionData_DataEntry_msg -#define waves_MassTransferTransactionData_fields \ - &waves_MassTransferTransactionData_msg +#define waves_MassTransferTransactionData_fields &waves_MassTransferTransactionData_msg #define waves_LeaseTransactionData_fields &waves_LeaseTransactionData_msg -#define waves_LeaseCancelTransactionData_fields \ - &waves_LeaseCancelTransactionData_msg +#define waves_LeaseCancelTransactionData_fields &waves_LeaseCancelTransactionData_msg #define waves_BurnTransactionData_fields &waves_BurnTransactionData_msg #define waves_IssueTransactionData_fields &waves_IssueTransactionData_msg #define waves_ReissueTransactionData_fields &waves_ReissueTransactionData_msg -#define waves_SetAssetScriptTransactionData_fields \ - &waves_SetAssetScriptTransactionData_msg -#define waves_SetScriptTransactionData_fields \ - &waves_SetScriptTransactionData_msg +#define waves_SetAssetScriptTransactionData_fields &waves_SetAssetScriptTransactionData_msg +#define waves_SetScriptTransactionData_fields &waves_SetScriptTransactionData_msg #define waves_ExchangeTransactionData_fields &waves_ExchangeTransactionData_msg -#define waves_SponsorFeeTransactionData_fields \ - &waves_SponsorFeeTransactionData_msg -#define waves_InvokeScriptTransactionData_fields \ - &waves_InvokeScriptTransactionData_msg -#define waves_UpdateAssetInfoTransactionData_fields \ - &waves_UpdateAssetInfoTransactionData_msg +#define waves_SponsorFeeTransactionData_fields &waves_SponsorFeeTransactionData_msg +#define waves_InvokeScriptTransactionData_fields &waves_InvokeScriptTransactionData_msg +#define waves_UpdateAssetInfoTransactionData_fields &waves_UpdateAssetInfoTransactionData_msg /* Maximum encoded size of messages (where known) */ /* waves_SignedTransaction_size depends on runtime parameters */ /* waves_Transaction_size depends on runtime parameters */ -/* waves_GenesisTransactionData_size depends on runtime parameters */ -/* waves_PaymentTransactionData_size depends on runtime parameters */ +#define waves_GenesisTransactionData_size 0 +#define waves_PaymentTransactionData_size 0 /* waves_TransferTransactionData_size depends on runtime parameters */ /* waves_CreateAliasTransactionData_size depends on runtime parameters */ -#define waves_DataTransactionData_size 0 -#define waves_DataTransactionData_DataEntry_size 0 +#define waves_DataTransactionData_size 0 /* waves_MassTransferTransactionData_size depends on runtime parameters */ -#define waves_LeaseTransactionData_size (17 + waves_Recipient_size) +#define waves_LeaseTransactionData_size 44 /* waves_LeaseCancelTransactionData_size depends on runtime parameters */ -#define waves_BurnTransactionData_size (6 + waves_Amount_size) +#define waves_BurnTransactionData_size (6 + waves_Amount_size) /* waves_IssueTransactionData_size depends on runtime parameters */ -#define waves_ReissueTransactionData_size (8 + waves_Amount_size) +#define waves_ReissueTransactionData_size (8 + waves_Amount_size) /* waves_SetAssetScriptTransactionData_size depends on runtime parameters */ -#define waves_SetScriptTransactionData_size 0 -/* waves_ExchangeTransactionData_size depends on runtime parameters */ -#define waves_SponsorFeeTransactionData_size (6 + waves_Amount_size) +#define waves_SetScriptTransactionData_size 0 +#define waves_ExchangeTransactionData_size 0 +#define waves_SponsorFeeTransactionData_size (6 + waves_Amount_size) /* waves_InvokeScriptTransactionData_size depends on runtime parameters */ /* waves_UpdateAssetInfoTransactionData_size depends on runtime parameters */ diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index 1c3726bc..fa8ec095 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -4343,7 +4343,7 @@ const bagl_element_t ui_approval_blue[] = { {{BAGL_LABELINE, 0x10, 130, 200, 160, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, BAGL_FONT_OPEN_SANS_LIGHT_16_22PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, - (const char *)tmp_ctx.signing_context.ui.line3, + (const char *)tmp_ctx.signing_context.first_data_hash, 0, 0, 0, diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index bee78b0b..300508f3 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -978,7 +978,7 @@ UX_STEP_NOCB(ux_verify_transaction_1_step, bnnn_paging, UX_STEP_NOCB(ux_verify_transaction_2_step, bnnn_paging, { .title = (const char *)tmp_ctx.signing_context.ui.line2, - .text = (const char *)tmp_ctx.signing_context.ui.line3, + .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); UX_STEP_NOCB(ux_verify_transaction_3_step, bnnn_paging, { diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 123f26c4..17e41263 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -23,29 +23,6 @@ #include "../print_amount.h" #include "../../crypto/waves.h" -// function to parse recipient in all transactions -// using autocallback in protofiles -// saving to 3 field -bool waves_Recipient_callback(pb_istream_t *istream, pb_ostream_t *ostream, - const pb_field_t *field) { - if (istream) { - PRINTF("Start Recipient callback\n"); - int len = istream->bytes_left; - os_memset(&G_io_apdu_buffer, 0, len); - if (!pb_read(istream, G_io_apdu_buffer, (size_t)istream->bytes_left)) { - return false; - } - if (field->tag == waves_Recipient_public_key_hash_tag) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, G_io_apdu_buffer, len); - tmp_ctx.signing_context.ui.pkhash = true; - } else if (field->tag == waves_Recipient_alias_tag) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, G_io_apdu_buffer, len); - } - PRINTF("End Recipient callback\n"); - } - return true; -} - bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start asset callback\n"); size_t length = 45; @@ -99,11 +76,11 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { if (!pb_read(stream, G_io_apdu_buffer, length)) { return false; } + os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); + os_memmove((char *)*arg, G_io_apdu_buffer, 45); if (!pb_read(stream, NULL, left)) { return false; } - os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); - os_memmove((char *)*arg, G_io_apdu_buffer, 45); } else { os_memset(&G_io_apdu_buffer, 0, len); if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { @@ -151,18 +128,18 @@ bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - if (field->tag == waves_Transaction_transfer_tag) { - waves_TransferTransactionData *tx = field->pData; - tx->amount.asset_id.funcs.decode = asset_callback; - tx->amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; - tx->attachment.funcs.decode = text_callback; - tx->attachment.arg = &tmp_ctx.signing_context.ui.line4; - } else if (field->tag == waves_Transaction_issue_tag) { + if (field->tag == waves_Transaction_issue_tag) { waves_IssueTransactionData *tx = field->pData; tx->name.funcs.decode = text_callback; tx->name.arg = &tmp_ctx.signing_context.ui.line1; tx->description.funcs.decode = text_callback; tx->description.arg = &tmp_ctx.signing_context.ui.line2; + } else if (field->tag == waves_Transaction_transfer_tag) { + waves_TransferTransactionData *tx = field->pData; + tx->amount.asset_id.funcs.decode = asset_callback; + tx->amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + tx->attachment.funcs.decode = text_callback; + tx->attachment.arg = &tmp_ctx.signing_context.ui.line4; } else if (field->tag == waves_Transaction_reissue_tag) { waves_ReissueTransactionData *tx = field->pData; tx->asset_amount.asset_id.funcs.decode = asset_callback; @@ -216,13 +193,19 @@ bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void make_transfer_ui(waves_Transaction *tx) { print_amount(tx->data.transfer.amount.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); + if(tx->data.transfer.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address( + tx->data.transfer.recipient.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } } void make_reissue_ui(waves_Transaction *tx) { print_amount(tx->data.reissue.asset_amount.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); if (tx->data.reissue.reissuable == true) { os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", 5); @@ -237,7 +220,7 @@ void make_issue_ui(waves_Transaction *tx) { sizeof(tmp_ctx.signing_context.ui.line4), "%d", tx->data.issue.decimals); print_amount(tx->data.issue.amount, (unsigned char)tx->data.issue.decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line3, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line3, 22); if (tx->data.issue.reissuable == true) { os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"True\0", 5); @@ -250,30 +233,42 @@ void make_issue_ui(waves_Transaction *tx) { void make_burn_ui(waves_Transaction *tx) { print_amount(tx->data.burn.asset_amount.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); } void make_start_leasing_ui(waves_Transaction *tx) { print_amount(tx->data.lease.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); + if(tx->data.lease.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address( + tx->data.lease.recipient.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } } void make_sponsorship_ui(waves_Transaction *tx) { print_amount(tx->data.sponsor_fee.min_fee.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); } void make_invoke_ui(waves_Transaction *tx) { if (tx->data.invoke_script.payments_count >= 1) { print_amount(tx->data.invoke_script.payments[0].amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)&tmp_ctx.signing_context.ui.line4, 20); + (unsigned char *)&tmp_ctx.signing_context.ui.line4, 22); } if (tx->data.invoke_script.payments_count == 2) { print_amount(tx->data.invoke_script.payments[1].amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)&tmp_ctx.signing_context.ui.line6, 20); + (unsigned char *)&tmp_ctx.signing_context.ui.line6, 22); + } + if(tx->data.invoke_script.d_app.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address( + tx->data.invoke_script.d_app.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); } } @@ -293,15 +288,18 @@ void build_protobuf_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buf total_buffer_size); // decoding tx message PRINTF("Start decoding\n"); - status = pb_decode(&stream, waves_Transaction_fields, &tx); + status = pb_decode_ex(&stream, waves_Transaction_fields, &tx, 0); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); - THROW(0x6D00); + THROW(SW_PROTOBUF_DECODING_FAILED); } PRINTF("End decoding\n"); + if(strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { + os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); + } print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); + (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 22); unsigned char tx_type = tmp_ctx.signing_context.data_type; // prepeare non callback data for viewing depend on tx type if (tx_type == 3) { @@ -340,7 +338,7 @@ void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, // create stream for parsing pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, total_buffer_size); - // decoding tx message + // decoding order message PRINTF("Start decoding\n"); status = pb_decode(&stream, waves_Order_fields, &order); if (!status) { @@ -349,9 +347,9 @@ void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, } PRINTF("End decoding\n"); print_amount(order.amount, tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line4, 20); + (unsigned char *)tmp_ctx.signing_context.ui.line4, 22); print_amount(order.matcher_fee.amount, tmp_ctx.signing_context.fee_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); + (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 22); if (order.order_side == waves_Order_Side_BUY) { os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Buy order\0", 10); diff --git a/src/ui/ui.c b/src/ui/ui.c index 6b015fdd..9b75ba9b 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -155,31 +155,152 @@ void build_other_data_ui() { tmp_ctx.signing_context.ui.finished = true; } +// getting message type based on tx type and varsion +int getMessageType() { + unsigned char tx_type = tmp_ctx.signing_context.data_type; + unsigned char tx_ver = tmp_ctx.signing_context.data_version; + // just one step here + if (tx_type == 3) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 4) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 5) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 6) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 8) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 9) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 10) { + if(tx_ver <= 2) { + return BYTE_DATA; + } else if(tx_ver >= 3) { + return PROTOBUF_DATA; + } + } else if (tx_type == 11) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver >= 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 12) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver == 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 13) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver == 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 14) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver == 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 15) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver == 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 16) { + if(tx_ver == 1) { + return BYTE_DATA; + } else if(tx_ver == 2) { + return PROTOBUF_DATA; + } + } else if (tx_type == 17) { + return PROTOBUF_DATA; + } else if (tx_type > 200) { + if (tx_type == 252) { + if(tx_ver <= 3) { + return BYTE_DATA; + } else if(tx_ver == 4) { + return PROTOBUF_DATA; + } + } else if (tx_type == 253) { + return BYTE_DATA; + } else if (tx_type == 254) { + return BYTE_DATA; + } else if (tx_type == 255) { + return BYTE_DATA; + } else { + return BYTE_DATA; + } + } + THROW(SW_INCORRECT_TRANSACTION_TYPE_VERSION); +} + void make_allowed_ui_steps(bool is_last) { - uint32_t start_index; + uint8_t start_index; + uint8_t chunk_size; PRINTF("make_allowed_ui_steps start\n"); - if (tmp_ctx.signing_context.data_version > 2) { // if protobuf + if (tmp_ctx.signing_context.message_type == PROTOBUF_DATA) { // if protobuf + if(is_last && G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used) { + THROW(SW_DEPRECATED_SIGN_PROTOCOL); + } if (tmp_ctx.signing_context.ui.finished != true) { + start_index = 5 + tmp_ctx.signing_context.chunk_used; + chunk_size = G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used; + if(tmp_ctx.signing_context.chunk == 0) { + start_index += 29; + chunk_size -= 29; + } if (tmp_ctx.signing_context.data_type == 252) { build_protobuf_order( &tmp_ctx.signing_context.ui.proto, - G_io_apdu_buffer + 5 + tmp_ctx.signing_context.chunk_used, - G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used, + G_io_apdu_buffer + start_index, + chunk_size, tmp_ctx.signing_context.data_size); } else { build_protobuf_tx( &tmp_ctx.signing_context.ui.proto, - G_io_apdu_buffer + 5 + tmp_ctx.signing_context.chunk_used, - G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used, + G_io_apdu_buffer + start_index, + chunk_size, tmp_ctx.signing_context.data_size); - } - + } } else { THROW(SW_INS_NOT_SUPPORTED); } } else { if (tmp_ctx.signing_context.ui.byte.step == 0) { + if(is_last && G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used) { + THROW(SW_DEPRECATED_SIGN_PROTOCOL); + } start_index = tmp_ctx.signing_context.chunk_used; + //if all data in one apdu move start index on 29 bytes to skip options data + if (tmp_ctx.signing_context.chunk == 0) { + start_index += 29; + } } else { start_index = tmp_ctx.signing_context.ui.byte.chunk_used; } diff --git a/src/ui/ui.h b/src/ui/ui.h index 8cf6511a..59a28af3 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -49,6 +49,7 @@ void show_sign_ui(); void show_sign_protobuf_ui(); void menu_address_init(); void show_processing(); +int getMessageType(); void try_to_fill_buffer(uint8_t chunk_data_start_index, uint8_t chunk_data_size); From b091a3e70fd021350a03ebbd2e0ec9cc4b9ccae7 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Tue, 8 Sep 2020 11:32:23 +0400 Subject: [PATCH 21/26] change protocol to send tx data 4 times due stack overflow, fix error with aliase in byte transaction --- proto/recipient.options | 2 +- proto/transaction.options | 8 +- python/ledger-waves.py | 8 +- src/main.c | 33 +-- src/main.h | 2 + src/nanopb/pb_custom.c | 27 +- src/nanopb/pb_custom.h | 3 +- src/nanopb/pb_decode.c | 1 - src/nanopb_stubs/recipient.pb.h | 4 +- src/nanopb_stubs/transaction.pb.h | 2 +- src/ui/transactions/protobuf.c | 478 +++++++++++++++++++----------- src/ui/transactions/protobuf.h | 8 +- src/ui/transactions/transfer.c | 21 +- src/ui/ui.c | 194 ++++++++---- 14 files changed, 491 insertions(+), 300 deletions(-) diff --git a/proto/recipient.options b/proto/recipient.options index d492c87a..19a1a976 100644 --- a/proto/recipient.options +++ b/proto/recipient.options @@ -1,2 +1,2 @@ waves.Recipient.public_key_hash max_size:20 fixed_length:true -waves.Recipient.alias max_size:30 \ No newline at end of file +waves.Recipient.alias max_size:31 \ No newline at end of file diff --git a/proto/transaction.options b/proto/transaction.options index ad63a74f..9bb25e6d 100644 --- a/proto/transaction.options +++ b/proto/transaction.options @@ -1,13 +1,13 @@ #Transaction filed sizes -waves.*.chain_id type: FT_IGNORE -waves.*.timestamp type: FT_IGNORE -waves.*.version type: FT_IGNORE +waves.Transaction.chain_id type: FT_IGNORE +waves.Transaction.timestamp type: FT_IGNORE +waves.Transaction.version type: FT_IGNORE waves.GenesisTransactionData type: FT_IGNORE waves.PaymentTransactionData type: FT_IGNORE -waves.ExchangeTransactionData type: FT_IGNORE +waves.ExchangeTransactionData type: FT_IGNORE waves.IssueTransactionData.script type: FT_IGNORE diff --git a/python/ledger-waves.py b/python/ledger-waves.py index 9f72e01a..620652fe 100644 --- a/python/ledger-waves.py +++ b/python/ledger-waves.py @@ -454,10 +454,6 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am sys.exit(0) sys.exc_clear() - tx = tpb.Transaction() - #tx.ParseFromString(base58.b58decode(" - # 8YifyLj9HucsDjXaLjPjUdb2kVVox3AyMaBjYAwzjkodkVQ5dEnXdYkPES6LVn9K3C2RGDCRAd69QYYRqL21T8xCKHGLhnvx5he1Mue22AQayB1qs7Q9vScYc4Dkqgo46BLmYU7KWBH5eDofqeD52e2o8hFbrnhYQ6Lzyg5Bt")) - #print(base58.b58encode(tx.transfer.amount.asset_id)) print(colors.fg.lightcyan + colors.bold + "Ledger Nano S - Waves test app" + colors.reset) print(colors.fg.white + @@ -520,6 +516,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am binary_data += some_transfer_bytes binary_data += some_transfer_bytes binary_data += some_transfer_bytes + binary_data += some_transfer_bytes print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) else: @@ -528,6 +525,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am binary_data += binary_input binary_data += binary_input binary_data += binary_input + binary_data += binary_input print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) print(colors.fg.lightgrey + "all request bytes: " + @@ -840,6 +838,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am binary_data += some_transfer_bytes binary_data += some_transfer_bytes binary_data += some_transfer_bytes + binary_data += some_transfer_bytes print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(some_transfer_bytes))) else: @@ -848,6 +847,7 @@ def build_order_protobuf(publicKey, matcherPK, amountAsset, priceAsset, type, am binary_data += binary_input binary_data += binary_input binary_data += binary_input + binary_data += binary_input print(colors.fg.lightgrey + "tx bytes: " + base58.b58encode(str(binary_input))) print(colors.fg.lightgrey + "all request bytes: " + diff --git a/src/main.c b/src/main.c index 27ecb813..865522c8 100644 --- a/src/main.c +++ b/src/main.c @@ -37,16 +37,6 @@ tmpContext_t tmp_ctx; // Non-volatile storage for the wallet app's stuff internal_storage_t const N_storage_real; -extern void _ebss; - - // Return true if there is less than MIN_BSS_STACK_GAP bytes available in the - // stack - void check_stack_overflow(int step) { - uint32_t stack_top = 0; - PRINTF("Stack remaining on step %d: CUR STACK ADDR: %p, EBSS: %p, diff: %d\n", step, &stack_top, &_ebss, ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); - //PRINTF("+++++++diff: %d\n", ((uintptr_t)&stack_top) - ((uintptr_t)&_ebss)); - } - // SPI Buffer for io_event unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; @@ -274,23 +264,14 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } if (G_io_apdu_buffer[2] == P1_LAST) { make_allowed_ui_steps(true); - if (tmp_ctx.signing_context.step != 7) { + if (tmp_ctx.signing_context.step != 8) { THROW(SW_DEPRECATED_SIGN_PROTOCOL); } } else { make_allowed_ui_steps(false); } // all data parsed and prepeared to view - if (tmp_ctx.signing_context.step == 7) { - os_memset(&G_io_apdu_buffer, 0, 64); - - cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, - G_io_apdu_buffer, 32); - // check view data eq to signed data - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, - &G_io_apdu_buffer, 32) != 0) { - THROW(SW_SIGN_DATA_NOT_MATCH); - } + if (tmp_ctx.signing_context.step == 8) { size_t length = 45; if (!b58enc((char *)tmp_ctx.signing_context.first_data_hash, &length, (const void *)&tmp_ctx.signing_context.first_data_hash, @@ -301,19 +282,9 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, waves_public_key_to_address(tmp_ctx.signing_context.ui.from, tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.from); - // if transaction has from field and it is pubkey hash will convert to // address - if (tmp_ctx.signing_context.ui.pkhash) { - - } if (tmp_ctx.signing_context.message_type == PROTOBUF_DATA) { - if (tmp_ctx.signing_context.data_type == 252) { - // convert matcher public key to address - waves_public_key_to_address(tmp_ctx.signing_context.ui.line2, - tmp_ctx.signing_context.network_byte, - tmp_ctx.signing_context.ui.line2); - } show_sign_protobuf_ui(); } else { show_sign_ui(); diff --git a/src/main.h b/src/main.h index c9a192ec..2084d02d 100644 --- a/src/main.h +++ b/src/main.h @@ -41,6 +41,7 @@ #define SW_INCORRECT_PRECISION_VALUE 0x9103 #define SW_INCORRECT_TRANSACTION_TYPE_VERSION 0x9104 #define SW_PROTOBUF_DECODING_FAILED 0x9105 +#define SW_BYTE_DECODING_FAILED 0x9106 #define SW_CONDITIONS_NOT_SATISFIED 0x6985 #define SW_DEVICE_IS_LOCKED 0x6986 #define SW_BUFFER_OVERFLOW 0x6990 @@ -71,6 +72,7 @@ typedef struct uiByte_t { uint8_t wait_in_buffer; uint8_t buffer_used; uint32_t chunk_used; + uint32_t total_received; uint16_t alias_size; uint16_t attachment_size; } uiByte_t; diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index 4b06b5ae..b178d51c 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -39,7 +39,6 @@ void fetch_new_apdu(uiProtobuf_t *state) { unsigned short sw = 0x9000; G_io_apdu_buffer[tx] = sw >> 8; G_io_apdu_buffer[tx + 1] = sw; - PRINTF("GET NEW APDU"); rx = io_exchange(CHANNEL_APDU | flags , 2); if (G_io_apdu_buffer[4] != rx - 5) { // the length of the APDU should match what's in the 5-byte header. @@ -55,7 +54,7 @@ void fetch_new_apdu(uiProtobuf_t *state) { THROW(ERR_BUFFER_TOO_SMALL); } - if (tmp_ctx.signing_context.step == 7) { + if (tmp_ctx.signing_context.step == 8) { THROW(SW_INCORRECT_P1_P2); } PRINTF("New APDU received:\n%.*H\n", rx, G_io_apdu_buffer); @@ -106,8 +105,13 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { // fetch next bytes fetch_new_apdu(state); // creating hash to check view and sign data are the same + int size = G_io_apdu_buffer[4]; + if((state->total_read + size + state->bytes_stored) > state->total_size) { + size = state->total_size - state->total_read - state->bytes_stored; + } + tmp_ctx.signing_context.sign_from = size; cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, - G_io_apdu_buffer + 5, G_io_apdu_buffer[4], NULL, 0); + G_io_apdu_buffer + 5, size, NULL, 0); os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, G_io_apdu_buffer[4]); @@ -139,10 +143,12 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { init_buffer: initialized the stream with some data (can be set to NULL) init_buffer_size: length of init_buffer total_buffer_size: total length of the message to receive + start_index: index from where starting new message in G_io_apdu_buffer */ pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, - uint16_t total_buffer_size) { + uint16_t total_buffer_size, + uint8_t start_index) { pb_istream_t stream; stream.callback = &apdu_read; stream.state = ctx; @@ -154,16 +160,17 @@ pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, ctx->total_received = init_buffer_size; ctx->total_size = total_buffer_size; os_memmove(ctx->data, init_buffer, init_buffer_size); + uint8_t hash_size = init_buffer_size; + //if chunk size bigger than message size + if(init_buffer_size > total_buffer_size) { + hash_size = total_buffer_size; + tmp_ctx.signing_context.sign_from = total_buffer_size + start_index - 5; + } cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, init_buffer, - init_buffer_size, NULL, 0); + hash_size, NULL, 0); ctx->bytes_stored = init_buffer_size; ctx->read_offset = 0; ctx->total_read = 0; -#ifdef HAVE_PRINTF - // Set call stack monitoring level to 0 - // G_depth = 0; -#endif - return stream; } diff --git a/src/nanopb/pb_custom.h b/src/nanopb/pb_custom.h index eafe5a8e..4e6d5f8a 100644 --- a/src/nanopb/pb_custom.h +++ b/src/nanopb/pb_custom.h @@ -17,7 +17,8 @@ pb_istream_t apdu_pb_istream(uiProtobuf_t *ctx, uint8_t *init_buffer, uint16_t total_buffer_size); pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, - uint16_t total_buffer_size); + uint16_t total_buffer_size, + uint8_t start_index); bool transaction_callback(pb_istream_t *stream, const pb_field_t *field, void **arg); bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg); diff --git a/src/nanopb/pb_decode.c b/src/nanopb/pb_decode.c index a7acc6d6..8e899048 100644 --- a/src/nanopb/pb_decode.c +++ b/src/nanopb/pb_decode.c @@ -1392,7 +1392,6 @@ static bool checkreturn pb_dec_string(pb_istream_t *stream, /* Space for null terminator */ alloc_size = (size_t)(size + 1); - if (alloc_size < size) PB_RETURN_ERROR(stream, "size too large"); diff --git a/src/nanopb_stubs/recipient.pb.h b/src/nanopb_stubs/recipient.pb.h index 46ca7f94..ad2cbd8a 100644 --- a/src/nanopb_stubs/recipient.pb.h +++ b/src/nanopb_stubs/recipient.pb.h @@ -18,7 +18,7 @@ typedef struct _waves_Recipient { pb_size_t which_recipient; union { pb_byte_t public_key_hash[20]; - char alias[30]; + char alias[31]; } recipient; } waves_Recipient; @@ -44,7 +44,7 @@ extern const pb_msgdesc_t waves_Recipient_msg; #define waves_Recipient_fields &waves_Recipient_msg /* Maximum encoded size of messages (where known) */ -#define waves_Recipient_size 31 +#define waves_Recipient_size 32 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/nanopb_stubs/transaction.pb.h b/src/nanopb_stubs/transaction.pb.h index c25c86a9..8e4c0260 100644 --- a/src/nanopb_stubs/transaction.pb.h +++ b/src/nanopb_stubs/transaction.pb.h @@ -434,7 +434,7 @@ extern const pb_msgdesc_t waves_UpdateAssetInfoTransactionData_msg; /* waves_CreateAliasTransactionData_size depends on runtime parameters */ #define waves_DataTransactionData_size 0 /* waves_MassTransferTransactionData_size depends on runtime parameters */ -#define waves_LeaseTransactionData_size 44 +#define waves_LeaseTransactionData_size 45 /* waves_LeaseCancelTransactionData_size depends on runtime parameters */ #define waves_BurnTransactionData_size (6 + waves_Amount_size) /* waves_IssueTransactionData_size depends on runtime parameters */ diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index 17e41263..f1706244 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -27,12 +27,13 @@ bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start asset callback\n"); size_t length = 45; int len = stream->bytes_left; - os_memset(&G_io_apdu_buffer, 0, len); - if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer[150], 0, len); + if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } if (len == 32) { - if (!b58enc((char *)*arg, &length, (const void *)G_io_apdu_buffer, 32)) { + if (!b58enc((char *)*arg, &length, (const void *)&G_io_apdu_buffer[150], + 32)) { return false; } } else { @@ -43,12 +44,12 @@ bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { } bool from_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - os_memset(&G_io_apdu_buffer, 0, 32); + os_memset(&G_io_apdu_buffer[150], 0, 32); PRINTF("Start from callback\n"); - if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { + if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, G_io_apdu_buffer, 32); + os_memmove((char *)*arg, &G_io_apdu_buffer[150], 32); PRINTF("End from callback\n"); return true; } @@ -57,11 +58,11 @@ bool string_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start string callback\n"); int len = stream->bytes_left; - os_memset(&G_io_apdu_buffer, 0, len); - if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer[150], 0, len); + if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, G_io_apdu_buffer, len); + os_memmove((char *)*arg, &G_io_apdu_buffer[150], len); PRINTF("End string callback\n"); return true; } @@ -71,22 +72,22 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start text callback\n"); if (len > 41) { size_t length = 41; - os_memset(&G_io_apdu_buffer, 0, 45); + os_memset(&G_io_apdu_buffer[150], 0, 45); size_t left = stream->bytes_left - length; - if (!pb_read(stream, G_io_apdu_buffer, length)) { + if (!pb_read(stream, &G_io_apdu_buffer[150], length)) { return false; } - os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); - os_memmove((char *)*arg, G_io_apdu_buffer, 45); + os_memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); + os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); if (!pb_read(stream, NULL, left)) { return false; } } else { - os_memset(&G_io_apdu_buffer, 0, len); - if (!pb_read(stream, G_io_apdu_buffer, (size_t)stream->bytes_left)) { + os_memset(&G_io_apdu_buffer[150], 0, len); + if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, G_io_apdu_buffer, len); + os_memmove((char *)*arg, &G_io_apdu_buffer[150], len); } PRINTF("End text callback\n"); return true; @@ -95,133 +96,106 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { uint32_t name_len; - os_memset(&G_io_apdu_buffer, 0, 45); + PRINTF("Start function call callback\n"); + os_memset(&G_io_apdu_buffer[150], 0, 45); int len = stream->bytes_left; - if (!pb_read(stream, G_io_apdu_buffer, + if (len <= 7) { + os_memmove((char *)*arg, &"default\0", 45); + return true; + } + if (!pb_read(stream, &G_io_apdu_buffer[150], 7)) { // read setting 3 bytes and 4 byte of function name size return false; } len -= 7; - name_len = deserialize_uint32_t(&G_io_apdu_buffer[3]); - if (name_len > 41) { // if function name len is - if (!pb_read(stream, G_io_apdu_buffer, 41)) { // read 41 byte of the name + name_len = deserialize_uint32_t(&G_io_apdu_buffer[153]); + if (name_len > 41) { // if function name len is + if (!pb_read(stream, &G_io_apdu_buffer[150], + 41)) { // read 41 byte of the name return false; } len -= 41; - os_memmove((char *)&G_io_apdu_buffer[41], &"...\0", 4); - os_memmove((char *)*arg, G_io_apdu_buffer, 45); + os_memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); + os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); if (!pb_read(stream, NULL, len)) { // read last str to null return false; } } else { - if (!pb_read(stream, G_io_apdu_buffer, name_len)) { // read all name str + if (!pb_read(stream, &G_io_apdu_buffer[150], + name_len)) { // read all name str return false; } len -= name_len; - os_memmove((char *)*arg, G_io_apdu_buffer, 45); - if (!pb_read(stream, NULL, len)) { //read other data + os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); + if (!pb_read(stream, NULL, len)) { // read other data return false; } } + PRINTF("End function call callback\n"); return true; } bool transaction_data_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - if (field->tag == waves_Transaction_issue_tag) { - waves_IssueTransactionData *tx = field->pData; - tx->name.funcs.decode = text_callback; - tx->name.arg = &tmp_ctx.signing_context.ui.line1; - tx->description.funcs.decode = text_callback; - tx->description.arg = &tmp_ctx.signing_context.ui.line2; - } else if (field->tag == waves_Transaction_transfer_tag) { - waves_TransferTransactionData *tx = field->pData; - tx->amount.asset_id.funcs.decode = asset_callback; - tx->amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; - tx->attachment.funcs.decode = text_callback; - tx->attachment.arg = &tmp_ctx.signing_context.ui.line4; - } else if (field->tag == waves_Transaction_reissue_tag) { - waves_ReissueTransactionData *tx = field->pData; - tx->asset_amount.asset_id.funcs.decode = asset_callback; - tx->asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; - } else if (field->tag == waves_Transaction_burn_tag) { - waves_BurnTransactionData *tx = field->pData; - tx->asset_amount.asset_id.funcs.decode = asset_callback; - tx->asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; - } else if (field->tag == waves_Transaction_lease_cancel_tag) { - waves_LeaseCancelTransactionData *tx = field->pData; - tx->lease_id.funcs.decode = asset_callback; - tx->lease_id.arg = &tmp_ctx.signing_context.ui.line1; - } else if (field->tag == waves_Transaction_create_alias_tag) { - waves_CreateAliasTransactionData *tx = field->pData; - tx->alias.funcs.decode = string_callback; - tx->alias.arg = &tmp_ctx.signing_context.ui.line1; - } else if (field->tag == waves_Transaction_mass_transfer_tag) { - waves_MassTransferTransactionData *tx = field->pData; - tx->asset_id.funcs.decode = asset_callback; - tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; - tx->attachment.funcs.decode = text_callback; - tx->attachment.arg = &tmp_ctx.signing_context.ui.line2; - } else if (field->tag == waves_Transaction_set_asset_script_tag) { - waves_SetAssetScriptTransactionData *tx = field->pData; - tx->asset_id.funcs.decode = asset_callback; - tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; - } else if (field->tag == waves_Transaction_sponsor_fee_tag) { - waves_SponsorFeeTransactionData *tx = field->pData; - tx->min_fee.asset_id.funcs.decode = asset_callback; - tx->min_fee.asset_id.arg = &tmp_ctx.signing_context.ui.line2; - } else if (field->tag == waves_Transaction_update_asset_info_tag) { - waves_UpdateAssetInfoTransactionData *tx = field->pData; - tx->asset_id.funcs.decode = asset_callback; - tx->asset_id.arg = &tmp_ctx.signing_context.ui.line1; - tx->name.funcs.decode = string_callback; - tx->name.arg = &tmp_ctx.signing_context.ui.line2; - tx->description.funcs.decode = text_callback; - tx->description.arg = &tmp_ctx.signing_context.ui.line4; - } else if (field->tag == waves_Transaction_invoke_script_tag) { - waves_InvokeScriptTransactionData *tx = field->pData; - tx->function_call.funcs.decode = function_call_callback; - tx->function_call.arg = &tmp_ctx.signing_context.ui.line2; - tx->payments[0].asset_id.funcs.decode = asset_callback; - tx->payments[0].asset_id.arg = &tmp_ctx.signing_context.ui.line1; - tx->payments[1].asset_id.funcs.decode = asset_callback; - tx->payments[1].asset_id.arg = &tmp_ctx.signing_context.ui.line5; + if (!pb_read(stream, NULL, stream->bytes_left)) { + return false; } return true; } -void make_transfer_ui(waves_Transaction *tx) { - print_amount(tx->data.transfer.amount.amount, - tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); - if(tx->data.transfer.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { - waves_public_key_hash_to_address( - tx->data.transfer.recipient.recipient.public_key_hash, - tmp_ctx.signing_context.network_byte, - tmp_ctx.signing_context.ui.line3); +uint32_t pb_find_child(pb_istream_t *stream) { + pb_wire_type_t wire_type; + uint32_t tag; + bool eof; + PRINTF("Start finding child msg\n"); + while (pb_decode_tag(stream, &wire_type, &tag, &eof)) { + if (wire_type == PB_WT_STRING) { + pb_field_iter_t iter; + if (pb_field_iter_begin(&iter, waves_Transaction_fields, NULL) && + pb_field_iter_find(&iter, tag)) { + if (tag >= waves_Transaction_issue_tag && + tag <= waves_Transaction_update_asset_info_tag) { + return tag; + } + } + } + + /* Wasn't our field.. */ + pb_skip_field(stream, wire_type); } + return 0; + PRINTF("End finding child msg\n"); } -void make_reissue_ui(waves_Transaction *tx) { - print_amount(tx->data.reissue.asset_amount.amount, - tmp_ctx.signing_context.amount_decimals, - (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); - if (tx->data.reissue.reissuable == true) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", - 5); - } else { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"False\0", - 6); +void pb_decode_child(pb_istream_t *stream, const pb_msgdesc_t *msg, + void *dest) { + PRINTF("Start decoding child msg\n"); + pb_istream_t substream; + uint8_t status; + if (!pb_make_string_substream(stream, &substream)) + THROW(SW_PROTOBUF_DECODING_FAILED); + + status = pb_decode(&substream, msg, dest); + pb_close_string_substream(stream, &substream); + if (!status) { + PRINTF("Decoding failed: %s\n", PB_GET_ERROR(stream)); + THROW(SW_PROTOBUF_DECODING_FAILED); } + PRINTF("End decoding child msg\n"); } -void make_issue_ui(waves_Transaction *tx) { +void build_issue_protobuf(pb_istream_t *stream) { + waves_IssueTransactionData tx = waves_IssueTransactionData_init_default; + tx.name.funcs.decode = text_callback; + tx.name.arg = &tmp_ctx.signing_context.ui.line1; + tx.description.funcs.decode = text_callback; + tx.description.arg = &tmp_ctx.signing_context.ui.line2; + pb_decode_child(stream, waves_IssueTransactionData_fields, &tx); snprintf((char *)tmp_ctx.signing_context.ui.line4, - sizeof(tmp_ctx.signing_context.ui.line4), "%d", - tx->data.issue.decimals); - print_amount(tx->data.issue.amount, (unsigned char)tx->data.issue.decimals, + sizeof(tmp_ctx.signing_context.ui.line4), "%d", tx.decimals); + print_amount(tx.amount, (unsigned char)tx.decimals, (unsigned char *)tmp_ctx.signing_context.ui.line3, 22); - if (tx->data.issue.reissuable == true) { + if (tx.reissuable == true) { os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"True\0", 5); } else { @@ -230,100 +204,263 @@ void make_issue_ui(waves_Transaction *tx) { } } -void make_burn_ui(waves_Transaction *tx) { - print_amount(tx->data.burn.asset_amount.amount, - tmp_ctx.signing_context.amount_decimals, +void build_transfer_protobuf(pb_istream_t *stream) { + waves_TransferTransactionData tx = waves_TransferTransactionData_init_default; + tx.amount.asset_id.funcs.decode = asset_callback; + tx.amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + tx.attachment.funcs.decode = text_callback; + tx.attachment.arg = &tmp_ctx.signing_context.ui.line4; + pb_decode_child(stream, waves_TransferTransactionData_fields, &tx); + print_amount(tx.amount.amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); + if (tx.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address(tx.recipient.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } else { + os_memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, + 31); + } + if (strlen((const char *)tmp_ctx.signing_context.ui.line2) == 0) { + os_memmove(tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); + } } -void make_start_leasing_ui(waves_Transaction *tx) { - print_amount(tx->data.lease.amount, tmp_ctx.signing_context.amount_decimals, +void build_reissue_protobuf(pb_istream_t *stream) { + waves_ReissueTransactionData tx = waves_ReissueTransactionData_init_default; + tx.asset_amount.asset_id.funcs.decode = asset_callback; + tx.asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + pb_decode_child(stream, waves_ReissueTransactionData_fields, &tx); + print_amount(tx.asset_amount.amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); - if(tx->data.lease.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { - waves_public_key_hash_to_address( - tx->data.lease.recipient.recipient.public_key_hash, - tmp_ctx.signing_context.network_byte, - tmp_ctx.signing_context.ui.line3); + if (tx.reissuable == true) { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", + 5); + } else { + os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"False\0", + 6); } } -void make_sponsorship_ui(waves_Transaction *tx) { - print_amount(tx->data.sponsor_fee.min_fee.amount, - tmp_ctx.signing_context.amount_decimals, +void build_burn_protobuf(pb_istream_t *stream) { + waves_BurnTransactionData tx = waves_BurnTransactionData_init_default; + tx.asset_amount.asset_id.funcs.decode = asset_callback; + tx.asset_amount.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + pb_decode_child(stream, waves_BurnTransactionData_fields, &tx); + print_amount(tx.asset_amount.amount, tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); +} + +void build_lease_protobuf(pb_istream_t *stream) { + waves_LeaseTransactionData tx = waves_LeaseTransactionData_init_default; + pb_decode_child(stream, waves_LeaseTransactionData_fields, &tx); + print_amount(tx.amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); + if (tx.recipient.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address(tx.recipient.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } else { + os_memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, + 31); + } +} + +void build_lease_cancel_protobuf(pb_istream_t *stream) { + waves_LeaseCancelTransactionData tx = + waves_LeaseCancelTransactionData_init_default; + tx.lease_id.funcs.decode = asset_callback; + tx.lease_id.arg = &tmp_ctx.signing_context.ui.line1; + pb_decode_child(stream, waves_LeaseCancelTransactionData_fields, &tx); +} + +void build_create_alias_protobuf(pb_istream_t *stream) { + waves_CreateAliasTransactionData tx = + waves_CreateAliasTransactionData_init_default; + tx.alias.funcs.decode = string_callback; + tx.alias.arg = &tmp_ctx.signing_context.ui.line1; + pb_decode_child(stream, waves_CreateAliasTransactionData_fields, &tx); +} + +void build_mass_transfer_protobuf(pb_istream_t *stream) { + waves_MassTransferTransactionData tx = + waves_MassTransferTransactionData_init_default; + tx.asset_id.funcs.decode = asset_callback; + tx.asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx.attachment.funcs.decode = text_callback; + tx.attachment.arg = &tmp_ctx.signing_context.ui.line2; + pb_decode_child(stream, waves_MassTransferTransactionData_fields, &tx); + if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { + os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + } } -void make_invoke_ui(waves_Transaction *tx) { - if (tx->data.invoke_script.payments_count >= 1) { - print_amount(tx->data.invoke_script.payments[0].amount, - tmp_ctx.signing_context.amount_decimals, +void build_data_transaction_protobuf(pb_istream_t *stream) { + waves_DataTransactionData tx = waves_DataTransactionData_init_default; + pb_decode_child(stream, waves_DataTransactionData_fields, &tx); +} + +void build_set_script_protobuf(pb_istream_t *stream) { + waves_SetScriptTransactionData tx = + waves_SetScriptTransactionData_init_default; + pb_decode_child(stream, waves_SetScriptTransactionData_fields, &tx); +} + +void build_sponsor_fee_protobuf(pb_istream_t *stream) { + waves_SponsorFeeTransactionData tx = + waves_SponsorFeeTransactionData_init_default; + tx.min_fee.asset_id.funcs.decode = asset_callback; + tx.min_fee.asset_id.arg = &tmp_ctx.signing_context.ui.line2; + pb_decode_child(stream, waves_SponsorFeeTransactionData_fields, &tx); + print_amount(tx.min_fee.amount, tmp_ctx.signing_context.amount_decimals, + (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); +} + +void build_set_asset_script_protobuf(pb_istream_t *stream) { + waves_SetAssetScriptTransactionData tx = + waves_SetAssetScriptTransactionData_init_default; + tx.asset_id.funcs.decode = asset_callback; + tx.asset_id.arg = &tmp_ctx.signing_context.ui.line1; + pb_decode_child(stream, waves_SetAssetScriptTransactionData_fields, &tx); +} + +void build_invoke_script_protobuf(pb_istream_t *stream) { + waves_InvokeScriptTransactionData tx = + waves_InvokeScriptTransactionData_init_default; + tx.function_call.funcs.decode = function_call_callback; + tx.function_call.arg = &tmp_ctx.signing_context.ui.line2; + tx.payments[0].asset_id.funcs.decode = asset_callback; + tx.payments[0].asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx.payments[1].asset_id.funcs.decode = asset_callback; + tx.payments[1].asset_id.arg = &tmp_ctx.signing_context.ui.line5; + pb_decode_child(stream, waves_InvokeScriptTransactionData_fields, &tx); + if (tx.payments_count >= 1) { + print_amount(tx.payments[0].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line4, 22); + if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { + os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + } } - if (tx->data.invoke_script.payments_count == 2) { - print_amount(tx->data.invoke_script.payments[1].amount, - tmp_ctx.signing_context.amount_decimals, + if (tx.payments_count == 2) { + print_amount(tx.payments[1].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line6, 22); + if (strlen((const char *)tmp_ctx.signing_context.ui.line5) == 0) { + os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + } } - if(tx->data.invoke_script.d_app.which_recipient == waves_Recipient_public_key_hash_tag) { - waves_public_key_hash_to_address( - tx->data.invoke_script.d_app.recipient.public_key_hash, - tmp_ctx.signing_context.network_byte, - tmp_ctx.signing_context.ui.line3); + if (tx.d_app.which_recipient == waves_Recipient_public_key_hash_tag) { + waves_public_key_hash_to_address(tx.d_app.recipient.public_key_hash, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line3); + } else { + os_memmove(tmp_ctx.signing_context.ui.line3, tx.d_app.recipient.alias, 31); } } -void build_protobuf_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, uint8_t init_buffer_size, - uint16_t total_buffer_size) { +void build_update_asset_info_protobuf(pb_istream_t *stream) { + waves_UpdateAssetInfoTransactionData tx = + waves_UpdateAssetInfoTransactionData_init_default; + tx.asset_id.funcs.decode = asset_callback; + tx.asset_id.arg = &tmp_ctx.signing_context.ui.line1; + tx.name.funcs.decode = string_callback; + tx.name.arg = &tmp_ctx.signing_context.ui.line2; + tx.description.funcs.decode = text_callback; + tx.description.arg = &tmp_ctx.signing_context.ui.line4; + pb_decode_child(stream, waves_UpdateAssetInfoTransactionData_fields, &tx); +} + +void build_protobuf_child_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, + uint16_t total_buffer_size) { + uint32_t tag; + pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, + total_buffer_size, 0); + tag = pb_find_child(&stream); + switch (tag) { + case waves_Transaction_issue_tag: + build_issue_protobuf(&stream); + break; + case waves_Transaction_transfer_tag: + build_transfer_protobuf(&stream); + break; + case waves_Transaction_reissue_tag: + build_reissue_protobuf(&stream); + break; + case waves_Transaction_burn_tag: + build_burn_protobuf(&stream); + break; + case waves_Transaction_lease_tag: + build_lease_protobuf(&stream); + break; + case waves_Transaction_lease_cancel_tag: + build_lease_cancel_protobuf(&stream); + break; + case waves_Transaction_create_alias_tag: + build_create_alias_protobuf(&stream); + break; + case waves_Transaction_mass_transfer_tag: + build_mass_transfer_protobuf(&stream); + break; + case waves_Transaction_data_transaction_tag: + build_data_transaction_protobuf(&stream); + break; + case waves_Transaction_set_script_tag: + build_set_script_protobuf(&stream); + break; + case waves_Transaction_sponsor_fee_tag: + build_sponsor_fee_protobuf(&stream); + break; + case waves_Transaction_set_asset_script_tag: + build_set_asset_script_protobuf(&stream); + break; + case waves_Transaction_invoke_script_tag: + build_invoke_script_protobuf(&stream); + break; + case waves_Transaction_update_asset_info_tag: + build_update_asset_info_protobuf(&stream); + break; + default: + PRINTF("Error with child tag"); + THROW(SW_PROTOBUF_DECODING_FAILED); + break; + } + + tmp_ctx.signing_context.ui.finished = true; + tmp_ctx.signing_context.step = 8; +} + +void build_protobuf_root_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, + uint16_t total_buffer_size, uint8_t start_index) { uint8_t status; + pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, + total_buffer_size, start_index); + PRINTF("Start decoding root msg\n"); // init variable for parsing - waves_Transaction tx = waves_Transaction_init_default; + waves_Transaction tx = waves_Transaction_init_zero; // set callback for parsing tx data field(transactions) tx.cb_data.funcs.decode = transaction_data_callback; tx.sender_public_key.funcs.decode = from_callback; tx.sender_public_key.arg = &tmp_ctx.signing_context.ui.from; tx.fee.asset_id.funcs.decode = asset_callback; tx.fee.asset_id.arg = &tmp_ctx.signing_context.ui.fee_asset; - // create stream for parsing - pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, - total_buffer_size); - // decoding tx message - PRINTF("Start decoding\n"); status = pb_decode_ex(&stream, waves_Transaction_fields, &tx, 0); if (!status) { PRINTF("Decoding failed: %s\n", PB_GET_ERROR(&stream)); THROW(SW_PROTOBUF_DECODING_FAILED); } - PRINTF("End decoding\n"); - - if(strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { - os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); - } print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 22); - unsigned char tx_type = tmp_ctx.signing_context.data_type; - // prepeare non callback data for viewing depend on tx type - if (tx_type == 3) { - make_issue_ui(&tx); - } else if (tx_type == 4) { - make_transfer_ui(&tx); - } else if (tx_type == 5) { - make_reissue_ui(&tx); - } else if (tx_type == 6) { - make_burn_ui(&tx); - } else if (tx_type == 8) { - make_start_leasing_ui(&tx); - } else if (tx_type == 14) { - make_sponsorship_ui(&tx); - } else if (tx_type == 16) { - make_invoke_ui(&tx); + if (strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { + os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); } - // finish parsing and view data + PRINTF("End decoding root msg\n"); tmp_ctx.signing_context.step = 7; - tmp_ctx.signing_context.ui.finished = true; } void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, - uint8_t init_buffer_size, uint16_t total_buffer_size) { + uint8_t init_buffer_size, uint16_t total_buffer_size, + uint8_t start_index) { uint8_t status; // init variable for parsing waves_Order order = waves_Order_init_default; @@ -337,7 +474,7 @@ void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, order.asset_pair.amount_asset_id.arg = &tmp_ctx.signing_context.ui.line1; // create stream for parsing pb_istream_t stream = pb_istream_from_apdu(ctx, init_buffer, init_buffer_size, - total_buffer_size); + total_buffer_size, start_index); // decoding order message PRINTF("Start decoding\n"); status = pb_decode(&stream, waves_Order_fields, &order); @@ -357,8 +494,11 @@ void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Sell order\0", 11); } - - // finish parsing and view data + if (strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { + os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); + } + waves_public_key_to_address(tmp_ctx.signing_context.ui.line2, + tmp_ctx.signing_context.network_byte, + tmp_ctx.signing_context.ui.line2); tmp_ctx.signing_context.step = 7; - tmp_ctx.signing_context.ui.finished = true; } diff --git a/src/ui/transactions/protobuf.h b/src/ui/transactions/protobuf.h index cfc1bc17..1ce25abb 100644 --- a/src/ui/transactions/protobuf.h +++ b/src/ui/transactions/protobuf.h @@ -29,9 +29,11 @@ #include "../../nanopb_stubs/order.pb.h" #include "../../nanopb_stubs/transaction.pb.h" -void build_protobuf_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, - uint8_t init_buffer_size, uint16_t total_buffer_size); +void build_protobuf_root_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size, uint8_t start_index); +void build_protobuf_child_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, + uint8_t init_buffer_size, uint16_t total_buffer_size); void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, - uint8_t init_buffer_size, uint16_t total_buffer_size); + uint8_t init_buffer_size, uint16_t total_buffer_size, uint8_t start_index); #endif \ No newline at end of file diff --git a/src/ui/transactions/transfer.c b/src/ui/transactions/transfer.c index b8b3011f..6ef87cd6 100644 --- a/src/ui/transactions/transfer.c +++ b/src/ui/transactions/transfer.c @@ -180,7 +180,6 @@ void build_transfer_ui_step(bool is_last) { (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 20); tmp_ctx.signing_context.ui.byte.step = 9; - update_transfer_wait_in_buffer(); break; case 9: @@ -192,7 +191,6 @@ void build_transfer_ui_step(bool is_last) { } else { return THROW(SW_CONDITIONS_NOT_SATISFIED); } - update_transfer_wait_in_buffer(); break; case 10: @@ -201,24 +199,25 @@ void build_transfer_ui_step(bool is_last) { (const void *)tmp_ctx.signing_context.ui.byte.buffer, 26)) { return THROW(SW_CONDITIONS_NOT_SATISFIED); } - tmp_ctx.signing_context.ui.byte.step = 13; - update_transfer_wait_in_buffer(); break; case 11: // alias len // also skip address scheme byte (first 2) - copy_in_reverse_order( - (unsigned char *)&tmp_ctx.signing_context.ui.byte.alias_size, - (unsigned char *)&tmp_ctx.signing_context.ui.byte.buffer[2], 2); - + tmp_ctx.signing_context.ui.byte.alias_size = + tmp_ctx.signing_context.ui.byte.buffer[1] << 8 | + tmp_ctx.signing_context.ui.byte.buffer[2]; tmp_ctx.signing_context.ui.byte.step = 12; update_transfer_wait_in_buffer(); break; case 12: // alias + if (tmp_ctx.signing_context.ui.byte.alias_size > 30 || + tmp_ctx.signing_context.ui.byte.alias_size < 4) { + THROW(SW_BYTE_DECODING_FAILED); + } os_memmove((unsigned char *)tmp_ctx.signing_context.ui.line3, (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, tmp_ctx.signing_context.ui.byte.alias_size); @@ -254,10 +253,8 @@ void build_transfer_ui_step(bool is_last) { update_transfer_wait_in_buffer(); break; case 15: - if (is_last) { - tmp_ctx.signing_context.ui.finished = true; - tmp_ctx.signing_context.step = 7; - } + tmp_ctx.signing_context.ui.finished = true; + tmp_ctx.signing_context.step = 7; break; default: THROW(INVALID_COUNTER); diff --git a/src/ui/ui.c b/src/ui/ui.c index 9b75ba9b..19a008dc 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -155,96 +155,96 @@ void build_other_data_ui() { tmp_ctx.signing_context.ui.finished = true; } -// getting message type based on tx type and varsion +// getting message type based on tx type and version int getMessageType() { unsigned char tx_type = tmp_ctx.signing_context.data_type; - unsigned char tx_ver = tmp_ctx.signing_context.data_version; + unsigned char tx_ver = tmp_ctx.signing_context.data_version; // just one step here if (tx_type == 3) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 4) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 5) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 6) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 8) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 9) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 10) { - if(tx_ver <= 2) { + if (tx_ver <= 2) { return BYTE_DATA; - } else if(tx_ver >= 3) { + } else if (tx_ver >= 3) { return PROTOBUF_DATA; } } else if (tx_type == 11) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver >= 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 12) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver == 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 13) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver == 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 14) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver == 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 15) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver == 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 16) { - if(tx_ver == 1) { + if (tx_ver == 1) { return BYTE_DATA; - } else if(tx_ver == 2) { + } else if (tx_ver >= 2) { return PROTOBUF_DATA; } } else if (tx_type == 17) { return PROTOBUF_DATA; } else if (tx_type > 200) { if (tx_type == 252) { - if(tx_ver <= 3) { + if (tx_ver <= 3) { return BYTE_DATA; - } else if(tx_ver == 4) { + } else if (tx_ver >= 4) { return PROTOBUF_DATA; } } else if (tx_type == 253) { @@ -265,62 +265,134 @@ void make_allowed_ui_steps(bool is_last) { uint8_t chunk_size; PRINTF("make_allowed_ui_steps start\n"); if (tmp_ctx.signing_context.message_type == PROTOBUF_DATA) { // if protobuf - if(is_last && G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used) { + if (is_last && G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used && + tmp_ctx.signing_context.step == 6) { THROW(SW_DEPRECATED_SIGN_PROTOCOL); } if (tmp_ctx.signing_context.ui.finished != true) { start_index = 5 + tmp_ctx.signing_context.chunk_used; chunk_size = G_io_apdu_buffer[4] - tmp_ctx.signing_context.chunk_used; - if(tmp_ctx.signing_context.chunk == 0) { + if (tmp_ctx.signing_context.chunk == 0) { start_index += 29; chunk_size -= 29; } if (tmp_ctx.signing_context.data_type == 252) { - build_protobuf_order( - &tmp_ctx.signing_context.ui.proto, - G_io_apdu_buffer + start_index, - chunk_size, - tmp_ctx.signing_context.data_size); + if (tmp_ctx.signing_context.step == 6) { + build_protobuf_order(&tmp_ctx.signing_context.ui.proto, + G_io_apdu_buffer + start_index, chunk_size, + tmp_ctx.signing_context.data_size, start_index); + os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, + tmp_ctx.signing_context.ui.proto.data, 32); + // check view data eq to signed data + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { + THROW(SW_SIGN_DATA_NOT_MATCH); + } + } + //not parse 4 tx data because no child message in order proto message + if (is_last) { + tmp_ctx.signing_context.step = 8; + tmp_ctx.signing_context.ui.finished = true; + return; + } else { + THROW(SW_OK); + } + } else { - build_protobuf_tx( - &tmp_ctx.signing_context.ui.proto, - G_io_apdu_buffer + start_index, - chunk_size, - tmp_ctx.signing_context.data_size); - } + build_protobuf_root_tx(&tmp_ctx.signing_context.ui.proto, + G_io_apdu_buffer + start_index, chunk_size, + tmp_ctx.signing_context.data_size, start_index); + os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, + tmp_ctx.signing_context.ui.proto.data, 32); + // check view data eq to signed data + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { + THROW(SW_SIGN_DATA_NOT_MATCH); + } + os_memset(&tmp_ctx.signing_context.ui.proto, 0, + sizeof(tmp_ctx.signing_context.ui.proto)); + os_memset(&tmp_ctx.signing_context.ui.hash_ctx, 0, + sizeof(tmp_ctx.signing_context.ui.hash_ctx)); + cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); + build_protobuf_child_tx( + &tmp_ctx.signing_context.ui.proto, + G_io_apdu_buffer + 5 + tmp_ctx.signing_context.sign_from, + G_io_apdu_buffer[4] - tmp_ctx.signing_context.sign_from, + tmp_ctx.signing_context.data_size); + } + os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, + tmp_ctx.signing_context.ui.proto.data, 32); + // check view data eq to signed data + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { + THROW(SW_SIGN_DATA_NOT_MATCH); + } } else { THROW(SW_INS_NOT_SUPPORTED); } } else { - if (tmp_ctx.signing_context.ui.byte.step == 0) { - if(is_last && G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used) { + if (tmp_ctx.signing_context.ui.byte.step == 0 && + tmp_ctx.signing_context.step == 6) { + if (is_last && + G_io_apdu_buffer[4] == tmp_ctx.signing_context.chunk_used) { THROW(SW_DEPRECATED_SIGN_PROTOCOL); } start_index = tmp_ctx.signing_context.chunk_used; - //if all data in one apdu move start index on 29 bytes to skip options data + // if all data in one apdu move start index on 29 bytes to skip options + // data if (tmp_ctx.signing_context.chunk == 0) { start_index += 29; } } else { start_index = tmp_ctx.signing_context.ui.byte.chunk_used; } - - if (tmp_ctx.signing_context.data_type == 4) { - uint8_t chunk_data_size = G_io_apdu_buffer[4]; - while ( - (chunk_data_size - tmp_ctx.signing_context.ui.byte.chunk_used > 0 && - tmp_ctx.signing_context.ui.byte.step < 15) || - (tmp_ctx.signing_context.ui.byte.step == 15 && - !tmp_ctx.signing_context.ui.finished && is_last)) { - build_transfer_ui_step(is_last); + if (tmp_ctx.signing_context.step == 6) { + if (tmp_ctx.signing_context.data_type == 4) { + uint8_t chunk_data_size = G_io_apdu_buffer[4]; + while ( + (chunk_data_size - tmp_ctx.signing_context.ui.byte.chunk_used > 0 && + tmp_ctx.signing_context.ui.byte.step < 15) || + (tmp_ctx.signing_context.ui.byte.step == 15 && + !tmp_ctx.signing_context.ui.finished)) { + build_transfer_ui_step(is_last); + } + } else { + tmp_ctx.signing_context.ui.byte.step++; + } + uint8_t hash_data_size = G_io_apdu_buffer[4] - start_index; + bool last_hash = false; + if (tmp_ctx.signing_context.ui.byte.total_received + hash_data_size >= + tmp_ctx.signing_context.data_size) { + hash_data_size = tmp_ctx.signing_context.data_size - + tmp_ctx.signing_context.ui.byte.total_received; + last_hash = true; + tmp_ctx.signing_context.ui.byte.total_received = 0; + if (tmp_ctx.signing_context.data_type != 4) { + build_other_data_ui(); + tmp_ctx.signing_context.step = 7; + } + } + tmp_ctx.signing_context.ui.byte.total_received += hash_data_size; + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, + G_io_apdu_buffer + 5 + start_index, hash_data_size, NULL, 0); + if (last_hash) { + os_memset(&tmp_ctx.signing_context.ui.byte.buffer, 0, 64); + cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, + tmp_ctx.signing_context.ui.byte.buffer, 32); + // check view data eq to signed data + if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + &tmp_ctx.signing_context.ui.byte.buffer, 32) != 0) { + THROW(SW_SIGN_DATA_NOT_MATCH); + } } - } else if (is_last) { - build_other_data_ui(); - tmp_ctx.signing_context.step = 7; } - cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, - G_io_apdu_buffer + 5 + start_index, - G_io_apdu_buffer[4] - start_index, NULL, 0); + if (is_last) { + tmp_ctx.signing_context.step = 8; + } + tmp_ctx.signing_context.ui.byte.chunk_used = 0; } PRINTF("make_allowed_ui_steps end\n"); From 9c3b357d98f979aec982e23406bd7910e0934daa Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Wed, 21 Jul 2021 10:37:43 +0400 Subject: [PATCH 22/26] adaptations to new sdk 2.0.0 --- Makefile | 2 +- proto/transaction.options | 2 - src/crypto/ledger_crypto.c | 6 +-- src/crypto/stream_eddsa_sign.c | 47 ++++++++--------- src/crypto/waves.c | 9 ++-- src/main.c | 22 ++++---- src/nanopb/pb_custom.c | 8 +-- src/nanopb_stubs/transaction.pb.h | 9 ++-- src/ui/blue/ui_menus_blue.h | 31 ++++++++++++ src/ui/blue/ui_menus_blue_prepro.c | 1 + src/ui/blue/ui_menus_blue_prepro.h | 1 + src/ui/nanox/ui_menus_nanox.h | 18 ++++--- src/ui/print_amount.c | 3 +- src/ui/transactions/protobuf.c | 81 ++++++++++++++++++------------ src/ui/transactions/transfer.c | 16 +++--- src/ui/transactions/transfer.h | 2 +- src/ui/ui.c | 72 +++++++++++++------------- src/ui/ui.h | 1 + src/ui/ui_logic.c | 1 + src/ui/ui_logic.h | 1 + 20 files changed, 198 insertions(+), 135 deletions(-) diff --git a/Makefile b/Makefile index 5fe407f7..a44b6fba 100755 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 0 +DEBUG = 1 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) diff --git a/proto/transaction.options b/proto/transaction.options index 9bb25e6d..6958b9d0 100644 --- a/proto/transaction.options +++ b/proto/transaction.options @@ -9,8 +9,6 @@ waves.PaymentTransactionData type: FT_IGNORE waves.ExchangeTransactionData type: FT_IGNORE -waves.IssueTransactionData.script type: FT_IGNORE - waves.SetAssetScriptTransactionData.script type: FT_IGNORE waves.SetScriptTransactionData.script type: FT_IGNORE diff --git a/src/crypto/ledger_crypto.c b/src/crypto/ledger_crypto.c index 4cbf86a9..8029f017 100644 --- a/src/crypto/ledger_crypto.c +++ b/src/crypto/ledger_crypto.c @@ -37,8 +37,8 @@ void public_key_le_to_be(cx_ecfp_public_key_t *public_key) { if ((public_key->W[32] & 1) != 0) { public_key_be[31] |= 0x80; } - os_memset(public_key->W, 0, 65); - os_memmove(public_key->W, public_key_be, 32); + memset(public_key->W, 0, 65); + memmove(public_key->W, public_key_be, 32); } void get_keypair_by_path(const uint32_t *path, cx_ecfp_public_key_t *public_key, @@ -63,7 +63,7 @@ bool get_curve25519_public_key_for_path(const uint32_t *path, // derive the ed25519 keys by that BIP32 path from the device get_keypair_by_path(path, public_key, &private_key); // clean private key - os_memset(&private_key, 0, sizeof(cx_ecfp_private_key_t)); + memset(&private_key, 0, sizeof(cx_ecfp_private_key_t)); public_key_le_to_be(public_key); diff --git a/src/crypto/stream_eddsa_sign.c b/src/crypto/stream_eddsa_sign.c index a844e277..24f44140 100644 --- a/src/crypto/stream_eddsa_sign.c +++ b/src/crypto/stream_eddsa_sign.c @@ -19,6 +19,7 @@ ********************************************************************************/ #include "stream_eddsa_sign.h" +#include "string.h" #include "../main.h" static uint8_t const C_cx_Ed25519_a[] = { @@ -69,7 +70,7 @@ static uint8_t const C_cx_Ed25519_Qplus3div8[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; #define C_cx_Ed25519_h 8 -cx_curve_twisted_edward_t const C_cx_Ed25519 = { +cx_curve_twisted_edwards_t const C_cx_Ed25519 = { CX_CURVE_Ed25519, 256, 32, @@ -125,8 +126,8 @@ static void cx_eddsa_get_public_key_internal( const cx_ecfp_private_key_t *pv_key, cx_md_t hashID, cx_ecfp_public_key_t *pu_key, unsigned char *a, unsigned int a_len, unsigned char *h, unsigned int h_len, unsigned char *scal /*tmp*/) { - cx_curve_twisted_edward_t *domain = - (cx_curve_twisted_edward_t *)&C_cx_Ed25519; + cx_curve_twisted_edwards_t *domain = + (cx_curve_twisted_edwards_t *)&C_cx_Ed25519; cx_sha512_t hash_ctx; unsigned int size; @@ -155,7 +156,7 @@ static void cx_eddsa_get_public_key_internal( scal[31] = (scal[31] & 0x7F) | 0x40; } else { - os_memmove(scal, pv_key->d, pv_key->d_len); + memmove(scal, pv_key->d, pv_key->d_len); } /* 3. Interpret the buffer as the little-endian integer, forming a @@ -164,24 +165,24 @@ static void cx_eddsa_get_public_key_internal( */ cx_decode_int(scal, size); if (a) { - os_memmove(a, scal, size); + memmove(a, scal, size); } if (h) { - os_memmove(h, scal + size, size); + memmove(h, scal + size, size); } pu_key->curve = pv_key->curve; pu_key->W_len = 1 + size * 2; pu_key->W[0] = 0x04; - os_memmove(pu_key->W + 1, domain->Gx, size); - os_memmove(pu_key->W + 1 + size, domain->Gy, size); + memmove(pu_key->W + 1, domain->Gx, size); + memmove(pu_key->W + 1 + size, domain->Gy, size); cx_ecfp_scalar_mult(domain->curve, pu_key->W, pu_key->W_len, scal, size); } void stream_eddsa_sign_step1(streamEddsaContext_t *eddsa_context, const cx_ecfp_private_key_t *pv_key) { - os_memset((unsigned char *)eddsa_context, 0, sizeof(streamEddsaContext_t)); - cx_curve_twisted_edward_t *domain = - (cx_curve_twisted_edward_t *)&C_cx_Ed25519; + memset((unsigned char *)eddsa_context, 0, sizeof(streamEddsaContext_t)); + cx_curve_twisted_edwards_t *domain = + (cx_curve_twisted_edwards_t *)&C_cx_Ed25519; unsigned int size = domain->length; @@ -197,7 +198,7 @@ void stream_eddsa_sign_step1(streamEddsaContext_t *eddsa_context, cx_edward_compress_point(domain->curve, &eddsa_context->u.internal_pu_key.W[0], eddsa_context->u.internal_pu_key.W_len); - os_memmove(eddsa_context->Y, &eddsa_context->u.internal_pu_key.W[1], size); + memmove(eddsa_context->Y, &eddsa_context->u.internal_pu_key.W[1], size); // compute r // - last size (32/57) bytes of H(sk), h, as big endian bytes ordered. stored @@ -224,8 +225,8 @@ void stream_eddsa_sign_step2(streamEddsaContext_t *eddsa_context, void stream_eddsa_sign_step3(streamEddsaContext_t *eddsa_context) { unsigned char scal[64]; - cx_curve_twisted_edward_t *domain = - (cx_curve_twisted_edward_t *)&C_cx_Ed25519; + cx_curve_twisted_edwards_t *domain = + (cx_curve_twisted_edwards_t *)&C_cx_Ed25519; unsigned int size = domain->length; unsigned int hsize = 2 * size; @@ -234,16 +235,16 @@ void stream_eddsa_sign_step3(streamEddsaContext_t *eddsa_context) { cx_hash(&eddsa_context->hash_ctx.header, CX_LAST, NULL, 0, scal, 64); cx_encode_int(scal, hsize); cx_math_modm(scal, hsize, domain->n, size); - os_memmove(eddsa_context->r, scal + size, size); // r + memmove(eddsa_context->r, scal + size, size); // r // compute R = r.B eddsa_context->u.Q[0] = 0x04; - os_memmove(eddsa_context->u.Q + 1, domain->Gx, size); - os_memmove(eddsa_context->u.Q + 1 + size, domain->Gy, size); + memmove(eddsa_context->u.Q + 1, domain->Gx, size); + memmove(eddsa_context->u.Q + 1 + size, domain->Gy, size); cx_ecfp_scalar_mult(CX_CURVE_Ed25519, eddsa_context->u.Q, 1 + 2 * domain->length, eddsa_context->r, size); cx_compress(eddsa_context->u.Q + 1, size); - os_memmove(eddsa_context->sig, eddsa_context->u.Q + 1 + size, + memmove(eddsa_context->sig, eddsa_context->u.Q + 1 + size, size); // sig <- R // compute S = r+H(R,A,M).a @@ -267,15 +268,15 @@ void stream_eddsa_sign_step4(streamEddsaContext_t *eddsa_context, int stream_eddsa_sign_step5(streamEddsaContext_t *eddsa_context, unsigned char *sig) { unsigned char scal[64]; - cx_curve_twisted_edward_t *domain = - (cx_curve_twisted_edward_t *)&C_cx_Ed25519; + cx_curve_twisted_edwards_t *domain = + (cx_curve_twisted_edwards_t *)&C_cx_Ed25519; unsigned int size = domain->length; unsigned int hsize = 2 * size; unsigned char second_data_hash[64]; cx_hash(&eddsa_context->data_hash_ctx.header, CX_LAST, NULL, 0, second_data_hash, 32); - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, &second_data_hash, + if (memcmp(&tmp_ctx.signing_context.first_data_hash, &second_data_hash, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } @@ -291,8 +292,8 @@ int stream_eddsa_sign_step5(streamEddsaContext_t *eddsa_context, eddsa_context->r, domain->n, size); cx_encode_int(eddsa_context->sig + size, size); - os_memmove(sig, eddsa_context->sig, 64); - os_memset((unsigned char *)eddsa_context, 0, sizeof(streamEddsaContext_t)); + memmove(sig, eddsa_context->sig, 64); + memset((unsigned char *)eddsa_context, 0, sizeof(streamEddsaContext_t)); return 2 * size; } \ No newline at end of file diff --git a/src/crypto/waves.c b/src/crypto/waves.c index a790945f..85bded27 100644 --- a/src/crypto/waves.c +++ b/src/crypto/waves.c @@ -21,6 +21,7 @@ #include "waves.h" #include "ledger_crypto.h" #include "stream_eddsa_sign.h" +#include "string.h" void waves_secure_hash(const uint8_t *message, size_t message_len, uint8_t hash[32]) { @@ -40,11 +41,11 @@ void waves_public_key_to_address(const ed25519_public_key public_key, address[0] = 0x01; address[1] = network_byte; - os_memmove(&address[2], public_key_hash, 20); + memmove(&address[2], public_key_hash, 20); waves_secure_hash(address, 22, checksum); - os_memmove(&address[22], checksum, 4); + memmove(&address[22], checksum, 4); size_t length = 36; b58enc((char *)output, &length, address, 26); @@ -57,9 +58,9 @@ void waves_public_key_hash_to_address( uint8_t checksum[32]; address[0] = 0x01; address[1] = network_byte; - os_memmove(&address[2], public_key_hash, 20); + memmove(&address[2], public_key_hash, 20); waves_secure_hash(address, 22, checksum); - os_memmove(&address[22], checksum, 4); + memmove(&address[22], checksum, 4); size_t length = 36; b58enc((char *)output, &length, address, 26); } diff --git a/src/main.c b/src/main.c index 865522c8..53943e77 100644 --- a/src/main.c +++ b/src/main.c @@ -23,14 +23,14 @@ #include "main.h" #include "crypto/waves.h" #include "crypto/ledger_crypto.h" -#include "os_io_seproxyhal.h" // Ledger Stuff #include "ui/ui.h" #include "os.h" #include "cx.h" -#include "os_io_seproxyhal.h" +#include "ux.h" +uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; // Temporary area to store stuff and reuse the same memory tmpContext_t tmp_ctx; @@ -122,8 +122,8 @@ void make_sign_step(uint8_t chunk_data_start_index, uint8_t chunk_data_size) { &private_key); public_key_le_to_be(&public_key); tmp_ctx.signing_context.sign_bit = public_key.W[31] & 0x80; - os_memset(&private_key, 0, sizeof(cx_ecfp_private_key_t)); - os_memset(&public_key, 0, sizeof(cx_ecfp_public_key_t)); + memset(&private_key, 0, sizeof(cx_ecfp_private_key_t)); + memset(&public_key, 0, sizeof(cx_ecfp_public_key_t)); tmp_ctx.signing_context.step = 2; } else if (tmp_ctx.signing_context.step == 2) { if (tmp_ctx.signing_context.data_read < tmp_ctx.signing_context.data_size) { @@ -186,7 +186,7 @@ void make_allowed_sign_steps() { // https://github.com/lenondupe/ledger-app-stellar/blob/master/src/main.c#L1784 uint32_t set_result_sign() { tmp_ctx.signing_context.signature[63] |= tmp_ctx.signing_context.sign_bit; - os_memmove((char *)G_io_apdu_buffer, tmp_ctx.signing_context.signature, + memmove((char *)G_io_apdu_buffer, tmp_ctx.signing_context.signature, sizeof(tmp_ctx.signing_context.signature)); PRINTF("Signature:\n%.*H\n", 64, tmp_ctx.signing_context.signature); @@ -197,9 +197,9 @@ uint32_t set_result_sign() { } uint32_t set_result_get_address() { - os_memmove((char *)G_io_apdu_buffer, + memmove((char *)G_io_apdu_buffer, (char *)tmp_ctx.address_context.public_key, 32); - os_memmove((char *)G_io_apdu_buffer + 32, + memmove((char *)G_io_apdu_buffer + 32, (char *)tmp_ctx.address_context.address, 35); init_context(); return 67; @@ -254,7 +254,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, tmp_ctx.signing_context.signature); tmp_ctx.signing_context.step = 6; PRINTF("make_sign_steps end\n"); - os_memset(&tmp_ctx.signing_context.ui, 0, + memset(&tmp_ctx.signing_context.ui, 0, sizeof(tmp_ctx.signing_context.ui)); cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); } else { @@ -316,9 +316,9 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, unsigned char address[35]; waves_public_key_to_address(public_key.W, G_io_apdu_buffer[3], address); - os_memmove((char *)tmp_ctx.address_context.public_key, public_key.W, + memmove((char *)tmp_ctx.address_context.public_key, public_key.W, 32); - os_memmove((char *)tmp_ctx.address_context.address, address, 35); + memmove((char *)tmp_ctx.address_context.address, address, 35); // term byte for string shown tmp_ctx.address_context.address[35] = '\0'; @@ -372,7 +372,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, } } -void init_context() { os_memset(&tmp_ctx, 0, sizeof(tmp_ctx)); } +void init_context() { memset(&tmp_ctx, 0, sizeof(tmp_ctx)); } static void waves_main(void) { volatile unsigned int rx = 0; diff --git a/src/nanopb/pb_custom.c b/src/nanopb/pb_custom.c index b178d51c..bd22c8c4 100644 --- a/src/nanopb/pb_custom.c +++ b/src/nanopb/pb_custom.c @@ -82,7 +82,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { stop the s tream if the last apdu was already received*/ if (count > bytes_not_read_yet) { // shift data to the beginning of the buffer - os_memmove(state->data, state->data + state->read_offset, + memmove(state->data, state->data + state->read_offset, state->bytes_stored - state->read_offset); state->bytes_stored = bytes_not_read_yet; state->read_offset = 0; @@ -112,7 +112,7 @@ bool checkreturn apdu_read(pb_istream_t *stream, pb_byte_t *buf, size_t count) { tmp_ctx.signing_context.sign_from = size; cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, G_io_apdu_buffer + 5, size, NULL, 0); - os_memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, + memmove(state->data + state->bytes_stored, G_io_apdu_buffer + 5, G_io_apdu_buffer[4]); state->bytes_stored += G_io_apdu_buffer[4]; @@ -156,10 +156,10 @@ pb_istream_t pb_istream_from_apdu(uiProtobuf_t *ctx, uint8_t *init_buffer, #ifndef PB_NO_ERRMSG stream.errmsg = NULL; #endif - os_memset(ctx, 0, sizeof(uiProtobuf_t)); + memset(ctx, 0, sizeof(uiProtobuf_t)); ctx->total_received = init_buffer_size; ctx->total_size = total_buffer_size; - os_memmove(ctx->data, init_buffer, init_buffer_size); + memmove(ctx->data, init_buffer, init_buffer_size); uint8_t hash_size = init_buffer_size; //if chunk size bigger than message size if(init_buffer_size > total_buffer_size) { diff --git a/src/nanopb_stubs/transaction.pb.h b/src/nanopb_stubs/transaction.pb.h index 8e4c0260..f831485a 100644 --- a/src/nanopb_stubs/transaction.pb.h +++ b/src/nanopb_stubs/transaction.pb.h @@ -79,6 +79,7 @@ typedef struct _waves_IssueTransactionData { int64_t amount; int32_t decimals; bool reissuable; + pb_callback_t script; } waves_IssueTransactionData; typedef struct _waves_LeaseTransactionData { @@ -153,7 +154,7 @@ typedef struct _waves_SignedTransaction { #define waves_LeaseTransactionData_init_default {false, waves_Recipient_init_default, 0} #define waves_LeaseCancelTransactionData_init_default {{{NULL}, NULL}} #define waves_BurnTransactionData_init_default {false, waves_Amount_init_default} -#define waves_IssueTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0} +#define waves_IssueTransactionData_init_default {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} #define waves_ReissueTransactionData_init_default {false, waves_Amount_init_default, 0} #define waves_SetAssetScriptTransactionData_init_default {{{NULL}, NULL}} #define waves_SetScriptTransactionData_init_default {0} @@ -172,7 +173,7 @@ typedef struct _waves_SignedTransaction { #define waves_LeaseTransactionData_init_zero {false, waves_Recipient_init_zero, 0} #define waves_LeaseCancelTransactionData_init_zero {{{NULL}, NULL}} #define waves_BurnTransactionData_init_zero {false, waves_Amount_init_zero} -#define waves_IssueTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0} +#define waves_IssueTransactionData_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, 0, 0, 0, {{NULL}, NULL}} #define waves_ReissueTransactionData_init_zero {false, waves_Amount_init_zero, 0} #define waves_SetAssetScriptTransactionData_init_zero {{{NULL}, NULL}} #define waves_SetScriptTransactionData_init_zero {0} @@ -199,6 +200,7 @@ typedef struct _waves_SignedTransaction { #define waves_IssueTransactionData_amount_tag 3 #define waves_IssueTransactionData_decimals_tag 4 #define waves_IssueTransactionData_reissuable_tag 5 +#define waves_IssueTransactionData_script_tag 6 #define waves_LeaseTransactionData_recipient_tag 1 #define waves_LeaseTransactionData_amount_tag 2 #define waves_ReissueTransactionData_asset_amount_tag 1 @@ -336,7 +338,8 @@ X(a, CALLBACK, SINGULAR, STRING, name, 1) \ X(a, CALLBACK, SINGULAR, STRING, description, 2) \ X(a, STATIC, SINGULAR, INT64, amount, 3) \ X(a, STATIC, SINGULAR, INT32, decimals, 4) \ -X(a, STATIC, SINGULAR, BOOL, reissuable, 5) +X(a, STATIC, SINGULAR, BOOL, reissuable, 5) \ +X(a, CALLBACK, SINGULAR, BYTES, script, 6) #define waves_IssueTransactionData_CALLBACK pb_default_field_callback #define waves_IssueTransactionData_DEFAULT NULL diff --git a/src/ui/blue/ui_menus_blue.h b/src/ui/blue/ui_menus_blue.h index fa8ec095..97a386d7 100644 --- a/src/ui/blue/ui_menus_blue.h +++ b/src/ui/blue/ui_menus_blue.h @@ -23,6 +23,7 @@ #include "os.h" #include "cx.h" +#include "ux.h" #include "../ui_logic.h" ////////////////////////////////////////////////////////////////////////////// @@ -907,6 +908,36 @@ const bagl_element_t ui_verify_issue_blue[] = { NULL, NULL}, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, + 0}, + NULL, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_LABEL, 0x71, 30, 218, 100, 30, 0, 0, BAGL_FILL, 0x000000, COLOR_BG_1, + BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, + "hasScript", + 0, + 0, + 0, + NULL, + NULL, + NULL}, + // x-18 when ... + {{BAGL_LABEL, 0x11, 130, 218, 160, 30, 0, 0, BAGL_FILL, 0x000000, + COLOR_BG_1, + BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, + (const char *)tmp_ctx.signing_context.ui.line6, + 0, + 0, + 0, + NULL, + NULL, + NULL}, + {{BAGL_RECTANGLE, 0x31, 30, 231, 260, 1, 1, 0, 0, 0xEEEEEE, COLOR_BG_1, 0, 0}, NULL, diff --git a/src/ui/blue/ui_menus_blue_prepro.c b/src/ui/blue/ui_menus_blue_prepro.c index 78e95698..bc337e07 100644 --- a/src/ui/blue/ui_menus_blue_prepro.c +++ b/src/ui/blue/ui_menus_blue_prepro.c @@ -21,6 +21,7 @@ #include "ui_menus_blue_prepro.h" #include "../ui.h" +#include "ux.h" const bagl_element_t *ui_address_blue_prepro(const bagl_element_t *element) { return element; diff --git a/src/ui/blue/ui_menus_blue_prepro.h b/src/ui/blue/ui_menus_blue_prepro.h index befe4ea5..3c717690 100644 --- a/src/ui/blue/ui_menus_blue_prepro.h +++ b/src/ui/blue/ui_menus_blue_prepro.h @@ -22,6 +22,7 @@ #define __UI_MENUS_BLUE_PREPRO_H__ #include "os_io_seproxyhal.h" +#include "ux.h" const bagl_element_t *ui_address_blue_prepro(const bagl_element_t *element); const bagl_element_t *ui_idle_blue_prepro(const bagl_element_t *element); diff --git a/src/ui/nanox/ui_menus_nanox.h b/src/ui/nanox/ui_menus_nanox.h index 300508f3..e424a327 100644 --- a/src/ui/nanox/ui_menus_nanox.h +++ b/src/ui/nanox/ui_menus_nanox.h @@ -24,6 +24,7 @@ #include "os.h" #include "cx.h" +#include "ux.h" #include "../ui_logic.h" ////////////////////////////////////////////////////////////////////// @@ -231,33 +232,38 @@ UX_STEP_NOCB(ux_issue_6_step, bnnn_paging, .text = (const char *)tmp_ctx.signing_context.ui.line5, }); UX_STEP_NOCB(ux_issue_7_step, bnnn_paging, + { + .title = "hasScript", + .text = (const char *)tmp_ctx.signing_context.ui.line6, + }); +UX_STEP_NOCB(ux_issue_8_step, bnnn_paging, { .title = "Fee", .text = (const char *)tmp_ctx.signing_context.ui.fee_amount, }); -UX_STEP_NOCB(ux_issue_8_step, bnnn_paging, +UX_STEP_NOCB(ux_issue_9_step, bnnn_paging, { .title = "Fee asset", .text = (const char *)tmp_ctx.signing_context.ui.fee_asset, }); -UX_STEP_NOCB(ux_issue_9_step, bnnn_paging, +UX_STEP_NOCB(ux_issue_10_step, bnnn_paging, { .title = "From", .text = (const char *)tmp_ctx.signing_context.ui.from, }); -UX_STEP_NOCB(ux_issue_10_step, bnnn_paging, +UX_STEP_NOCB(ux_issue_11_step, bnnn_paging, { .title = "Transaction Id", .text = (const char *)tmp_ctx.signing_context.first_data_hash, }); -UX_STEP_VALID(ux_issue_11_step, pbb, io_seproxyhal_touch_sign_approve(NULL), +UX_STEP_VALID(ux_issue_12_step, pbb, io_seproxyhal_touch_sign_approve(NULL), { &C_icon_validate_14, "Accept", "and send", }); -UX_STEP_VALID(ux_issue_12_step, pb, io_seproxyhal_cancel(NULL), +UX_STEP_VALID(ux_issue_13_step, pb, io_seproxyhal_cancel(NULL), { &C_icon_crossmark, "Reject", @@ -266,7 +272,7 @@ UX_STEP_VALID(ux_issue_12_step, pb, io_seproxyhal_cancel(NULL), UX_FLOW(ux_issue_flow, &ux_issue_1_step, &ux_issue_2_step, &ux_issue_3_step, &ux_issue_4_step, &ux_issue_5_step, &ux_issue_6_step, &ux_issue_7_step, &ux_issue_8_step, &ux_issue_9_step, &ux_issue_10_step, - &ux_issue_11_step, &ux_issue_12_step); + &ux_issue_11_step, &ux_issue_12_step, &ux_issue_13_step); ////////////////////////////////////////////////////////////////////// diff --git a/src/ui/print_amount.c b/src/ui/print_amount.c index 8851613b..a8e788a2 100644 --- a/src/ui/print_amount.c +++ b/src/ui/print_amount.c @@ -18,6 +18,7 @@ * limitations under the License. ********************************************************************************/ +#include "string.h" #include "print_amount.h" bool print_amount(uint64_t amount, int decimals, unsigned char *out, @@ -28,7 +29,7 @@ bool print_amount(uint64_t amount, int decimals, unsigned char *out, if (decimals == 0) decimals--; - os_memset(tmp_ctx.signing_context.ui.tmp, 0, len); + memset(tmp_ctx.signing_context.ui.tmp, 0, len); for (i = 0; dVal > 0 || i < decimals + 2; i++) { if (dVal > 0) { tmp_ctx.signing_context.ui.tmp[i] = (char)((dVal % 10) + '0'); diff --git a/src/ui/transactions/protobuf.c b/src/ui/transactions/protobuf.c index f1706244..a09fab9d 100644 --- a/src/ui/transactions/protobuf.c +++ b/src/ui/transactions/protobuf.c @@ -27,7 +27,7 @@ bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start asset callback\n"); size_t length = 45; int len = stream->bytes_left; - os_memset(&G_io_apdu_buffer[150], 0, len); + memset(&G_io_apdu_buffer[150], 0, len); if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } @@ -37,19 +37,19 @@ bool asset_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { return false; } } else { - os_memmove((char *)*arg, WAVES_CONST, 5); + memmove((char *)*arg, WAVES_CONST, 5); } PRINTF("End asset callback\n"); return true; } bool from_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { - os_memset(&G_io_apdu_buffer[150], 0, 32); + memset(&G_io_apdu_buffer[150], 0, 32); PRINTF("Start from callback\n"); if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, &G_io_apdu_buffer[150], 32); + memmove((char *)*arg, &G_io_apdu_buffer[150], 32); PRINTF("End from callback\n"); return true; } @@ -58,11 +58,11 @@ bool string_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start string callback\n"); int len = stream->bytes_left; - os_memset(&G_io_apdu_buffer[150], 0, len); + memset(&G_io_apdu_buffer[150], 0, len); if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, &G_io_apdu_buffer[150], len); + memmove((char *)*arg, &G_io_apdu_buffer[150], len); PRINTF("End string callback\n"); return true; } @@ -72,35 +72,46 @@ bool text_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { PRINTF("Start text callback\n"); if (len > 41) { size_t length = 41; - os_memset(&G_io_apdu_buffer[150], 0, 45); + memset(&G_io_apdu_buffer[150], 0, 45); size_t left = stream->bytes_left - length; if (!pb_read(stream, &G_io_apdu_buffer[150], length)) { return false; } - os_memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); - os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); + memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); + memmove((char *)*arg, &G_io_apdu_buffer[150], 45); if (!pb_read(stream, NULL, left)) { return false; } } else { - os_memset(&G_io_apdu_buffer[150], 0, len); + memset(&G_io_apdu_buffer[150], 0, len); if (!pb_read(stream, &G_io_apdu_buffer[150], (size_t)stream->bytes_left)) { return false; } - os_memmove((char *)*arg, &G_io_apdu_buffer[150], len); + memmove((char *)*arg, &G_io_apdu_buffer[150], len); } PRINTF("End text callback\n"); return true; } +bool issue_script_callback(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + PRINTF("Start issue script callback\n"); + int len = stream->bytes_left; + if (!pb_read(stream, NULL, len)) { // read other data + return false; + } + memmove((char *)*arg, &"True\0", 5); + PRINTF("End issue script callback\n"); +} + bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) { uint32_t name_len; PRINTF("Start function call callback\n"); - os_memset(&G_io_apdu_buffer[150], 0, 45); + memset(&G_io_apdu_buffer[150], 0, 45); int len = stream->bytes_left; if (len <= 7) { - os_memmove((char *)*arg, &"default\0", 45); + memmove((char *)*arg, &"default\0", 45); return true; } if (!pb_read(stream, &G_io_apdu_buffer[150], @@ -115,8 +126,8 @@ bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, return false; } len -= 41; - os_memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); - os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); + memmove((char *)&G_io_apdu_buffer[191], &"...\0", 4); + memmove((char *)*arg, &G_io_apdu_buffer[150], 45); if (!pb_read(stream, NULL, len)) { // read last str to null return false; } @@ -126,7 +137,7 @@ bool function_call_callback(pb_istream_t *stream, const pb_field_t *field, return false; } len -= name_len; - os_memmove((char *)*arg, &G_io_apdu_buffer[150], 45); + memmove((char *)*arg, &G_io_apdu_buffer[150], 45); if (!pb_read(stream, NULL, len)) { // read other data return false; } @@ -190,16 +201,22 @@ void build_issue_protobuf(pb_istream_t *stream) { tx.name.arg = &tmp_ctx.signing_context.ui.line1; tx.description.funcs.decode = text_callback; tx.description.arg = &tmp_ctx.signing_context.ui.line2; + tx.script.funcs.decode = issue_script_callback; + tx.script.arg = &tmp_ctx.signing_context.ui.line6; pb_decode_child(stream, waves_IssueTransactionData_fields, &tx); snprintf((char *)tmp_ctx.signing_context.ui.line4, sizeof(tmp_ctx.signing_context.ui.line4), "%d", tx.decimals); print_amount(tx.amount, (unsigned char)tx.decimals, (unsigned char *)tmp_ctx.signing_context.ui.line3, 22); if (tx.reissuable == true) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"True\0", + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"True\0", 5); } else { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"False\0", + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line5, &"False\0", + 6); + } + if(strlen((const char *)tmp_ctx.signing_context.ui.line6) == 0) { + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line6, &"False\0", 6); } } @@ -218,11 +235,11 @@ void build_transfer_protobuf(pb_istream_t *stream) { tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.line3); } else { - os_memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, + memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, 31); } if (strlen((const char *)tmp_ctx.signing_context.ui.line2) == 0) { - os_memmove(tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); } } @@ -234,10 +251,10 @@ void build_reissue_protobuf(pb_istream_t *stream) { print_amount(tx.asset_amount.amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)tmp_ctx.signing_context.ui.line1, 22); if (tx.reissuable == true) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"True\0", 5); } else { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"False\0", + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"False\0", 6); } } @@ -261,7 +278,7 @@ void build_lease_protobuf(pb_istream_t *stream) { tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.line3); } else { - os_memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, + memmove(tmp_ctx.signing_context.ui.line3, tx.recipient.recipient.alias, 31); } } @@ -291,7 +308,7 @@ void build_mass_transfer_protobuf(pb_istream_t *stream) { tx.attachment.arg = &tmp_ctx.signing_context.ui.line2; pb_decode_child(stream, waves_MassTransferTransactionData_fields, &tx); if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { - os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); } } @@ -338,14 +355,14 @@ void build_invoke_script_protobuf(pb_istream_t *stream) { print_amount(tx.payments[0].amount, tmp_ctx.signing_context.amount_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line4, 22); if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { - os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); } } if (tx.payments_count == 2) { - print_amount(tx.payments[1].amount, tmp_ctx.signing_context.amount_decimals, + print_amount(tx.payments[1].amount, tmp_ctx.signing_context.amount2_decimals, (unsigned char *)&tmp_ctx.signing_context.ui.line6, 22); if (strlen((const char *)tmp_ctx.signing_context.ui.line5) == 0) { - os_memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.line1, WAVES_CONST, 5); } } if (tx.d_app.which_recipient == waves_Recipient_public_key_hash_tag) { @@ -353,7 +370,7 @@ void build_invoke_script_protobuf(pb_istream_t *stream) { tmp_ctx.signing_context.network_byte, tmp_ctx.signing_context.ui.line3); } else { - os_memmove(tmp_ctx.signing_context.ui.line3, tx.d_app.recipient.alias, 31); + memmove(tmp_ctx.signing_context.ui.line3, tx.d_app.recipient.alias, 31); } } @@ -452,7 +469,7 @@ void build_protobuf_root_tx(uiProtobuf_t *ctx, uint8_t *init_buffer, print_amount(tx.fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 22); if (strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { - os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); } PRINTF("End decoding root msg\n"); tmp_ctx.signing_context.step = 7; @@ -488,14 +505,14 @@ void build_protobuf_order(uiProtobuf_t *ctx, uint8_t *init_buffer, print_amount(order.matcher_fee.amount, tmp_ctx.signing_context.fee_decimals, (unsigned char *)tmp_ctx.signing_context.ui.fee_amount, 22); if (order.order_side == waves_Order_Side_BUY) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Buy order\0", 10); } else { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line3, &"Sell order\0", 11); } if (strlen((const char *)tmp_ctx.signing_context.ui.fee_asset) == 0) { - os_memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); + memmove(tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); } waves_public_key_to_address(tmp_ctx.signing_context.ui.line2, tmp_ctx.signing_context.network_byte, diff --git a/src/ui/transactions/transfer.c b/src/ui/transactions/transfer.c index 6ef87cd6..484853ac 100644 --- a/src/ui/transactions/transfer.c +++ b/src/ui/transactions/transfer.c @@ -33,7 +33,7 @@ void update_transfer_wait_in_buffer() { tmp_ctx.signing_context.ui.byte.wait_in_buffer = 1; break; case 11: - tmp_ctx.signing_context.ui.byte.wait_in_buffer = 4; + tmp_ctx.signing_context.ui.byte.wait_in_buffer = 3; break; case 13: tmp_ctx.signing_context.ui.byte.wait_in_buffer = 2; @@ -68,7 +68,7 @@ void update_transfer_wait_in_buffer() { } } -void build_transfer_ui_step(bool is_last) { +void build_transfer_ui_step() { uint8_t chunk_data_size = G_io_apdu_buffer[4]; uint8_t chunk_data_start_index = 5; @@ -102,7 +102,7 @@ void build_transfer_ui_step(bool is_last) { break; case 1: // sender public key 32 bytes - os_memmove(&tmp_ctx.signing_context.ui.from, + memmove(&tmp_ctx.signing_context.ui.from, tmp_ctx.signing_context.ui.byte.buffer, 32); tmp_ctx.signing_context.ui.byte.step = 2; @@ -113,7 +113,7 @@ void build_transfer_ui_step(bool is_last) { if (is_flag_set) { tmp_ctx.signing_context.ui.byte.step = 3; } else { - os_memmove((char *)tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); + memmove((char *)tmp_ctx.signing_context.ui.line2, WAVES_CONST, 5); tmp_ctx.signing_context.ui.byte.step = 4; } @@ -135,7 +135,7 @@ void build_transfer_ui_step(bool is_last) { if (is_flag_set) { tmp_ctx.signing_context.ui.byte.step = 5; } else { - os_memmove((char *)tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, + memmove((char *)tmp_ctx.signing_context.ui.fee_asset, WAVES_CONST, 5); tmp_ctx.signing_context.ui.byte.step = 6; } @@ -218,7 +218,7 @@ void build_transfer_ui_step(bool is_last) { tmp_ctx.signing_context.ui.byte.alias_size < 4) { THROW(SW_BYTE_DECODING_FAILED); } - os_memmove((unsigned char *)tmp_ctx.signing_context.ui.line3, + memmove((unsigned char *)tmp_ctx.signing_context.ui.line3, (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, tmp_ctx.signing_context.ui.byte.alias_size); @@ -239,12 +239,12 @@ void build_transfer_ui_step(bool is_last) { case 14: // attachment if (tmp_ctx.signing_context.ui.byte.attachment_size > 41) { - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.line4[41], + memmove((unsigned char *)&tmp_ctx.signing_context.ui.line4[41], &"...\0", 4); tmp_ctx.signing_context.ui.byte.attachment_size = 41; } - os_memmove((unsigned char *)tmp_ctx.signing_context.ui.line4, + memmove((unsigned char *)tmp_ctx.signing_context.ui.line4, (const unsigned char *)tmp_ctx.signing_context.ui.byte.buffer, tmp_ctx.signing_context.ui.byte.attachment_size); diff --git a/src/ui/transactions/transfer.h b/src/ui/transactions/transfer.h index 0fa0a17d..991354d9 100644 --- a/src/ui/transactions/transfer.h +++ b/src/ui/transactions/transfer.h @@ -23,6 +23,6 @@ #include -void build_transfer_ui_step(bool is_last); +void build_transfer_ui_step(); #endif \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index 19a008dc..3260fffa 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -80,7 +80,7 @@ void try_to_fill_buffer(uint8_t chunk_data_start_index, 150) { return THROW(EXCEPTION_OVERFLOW); } - os_memmove((unsigned char *)&tmp_ctx.signing_context.ui.byte + memmove((unsigned char *)&tmp_ctx.signing_context.ui.byte .buffer[tmp_ctx.signing_context.ui.byte.buffer_used], &G_io_apdu_buffer[chunk_data_start_index + tmp_ctx.signing_context.ui.byte.chunk_used], @@ -93,54 +93,54 @@ void try_to_fill_buffer(uint8_t chunk_data_start_index, void build_other_data_ui() { unsigned char tx_type = tmp_ctx.signing_context.data_type; // just one step here - os_memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Id\0", 15); + memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Id\0", 15); if (tx_type == 3) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"issue\0", 6); + memmove(&tmp_ctx.signing_context.ui.line1, &"issue\0", 6); } else if (tx_type == 4) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"transfer\0", 9); + memmove(&tmp_ctx.signing_context.ui.line1, &"transfer\0", 9); } else if (tx_type == 5) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"reissue\0", 8); + memmove(&tmp_ctx.signing_context.ui.line1, &"reissue\0", 8); } else if (tx_type == 6) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"burn\0", 5); + memmove(&tmp_ctx.signing_context.ui.line1, &"burn\0", 5); } else if (tx_type == 8) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"start leasing\0", 14); + memmove(&tmp_ctx.signing_context.ui.line1, &"start leasing\0", 14); } else if (tx_type == 9) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"cancel leasing\0", 15); + memmove(&tmp_ctx.signing_context.ui.line1, &"cancel leasing\0", 15); } else if (tx_type == 10) { - os_memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Hash\0", 17); - os_memmove(&tmp_ctx.signing_context.ui.line1, &"creating an alias\0", 18); + memmove(&tmp_ctx.signing_context.ui.line2, &"Transaction Hash\0", 17); + memmove(&tmp_ctx.signing_context.ui.line1, &"creating an alias\0", 18); } else if (tx_type == 11) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"mass transfer\0", 14); + memmove(&tmp_ctx.signing_context.ui.line1, &"mass transfer\0", 14); } else if (tx_type == 12) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); + memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); } else if (tx_type == 13) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"set script\0", 11); + memmove(&tmp_ctx.signing_context.ui.line1, &"set script\0", 11); } else if (tx_type == 14) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"sponsorship\0", 12); + memmove(&tmp_ctx.signing_context.ui.line1, &"sponsorship\0", 12); } else if (tx_type == 15) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"asset script\0", 13); + memmove(&tmp_ctx.signing_context.ui.line1, &"asset script\0", 13); } else if (tx_type == 16) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"script invocation\0", 18); + memmove(&tmp_ctx.signing_context.ui.line1, &"script invocation\0", 18); } else if (tx_type == 17) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"update asset info\0", 18); + memmove(&tmp_ctx.signing_context.ui.line1, &"update asset info\0", 18); } else if (tx_type > 200) { // type byte >200 are 'reserved', it will not be signed - os_memmove(&tmp_ctx.signing_context.ui.line2, &"Hash\0", 5); + memmove(&tmp_ctx.signing_context.ui.line2, &"Hash\0", 5); if (tx_type == 252) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"order\0", 6); + memmove(&tmp_ctx.signing_context.ui.line1, &"order\0", 6); } else if (tx_type == 253) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); + memmove(&tmp_ctx.signing_context.ui.line1, &"data\0", 5); } else if (tx_type == 254) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"request\0", 8); + memmove(&tmp_ctx.signing_context.ui.line1, &"request\0", 8); } else if (tx_type == 255) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"message\0", 8); + memmove(&tmp_ctx.signing_context.ui.line1, &"message\0", 8); } else { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"something\0", 10); + memmove(&tmp_ctx.signing_context.ui.line1, &"something\0", 10); } } if (strlen((const char *)tmp_ctx.signing_context.ui.line1) == 0) { - os_memmove(&tmp_ctx.signing_context.ui.line1, &"transaction\0", 12); + memmove(&tmp_ctx.signing_context.ui.line1, &"transaction\0", 12); } // Get the public key and return it. @@ -151,7 +151,7 @@ void build_other_data_ui() { THROW(INVALID_PARAMETER); } - os_memmove(&tmp_ctx.signing_context.ui.from, public_key.W, 32); + memmove(&tmp_ctx.signing_context.ui.from, public_key.W, 32); tmp_ctx.signing_context.ui.finished = true; } @@ -281,11 +281,11 @@ void make_allowed_ui_steps(bool is_last) { build_protobuf_order(&tmp_ctx.signing_context.ui.proto, G_io_apdu_buffer + start_index, chunk_size, tmp_ctx.signing_context.data_size, start_index); - os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, tmp_ctx.signing_context.ui.proto.data, 32); // check view data eq to signed data - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + if (memcmp(&tmp_ctx.signing_context.first_data_hash, &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } @@ -303,17 +303,17 @@ void make_allowed_ui_steps(bool is_last) { build_protobuf_root_tx(&tmp_ctx.signing_context.ui.proto, G_io_apdu_buffer + start_index, chunk_size, tmp_ctx.signing_context.data_size, start_index); - os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, tmp_ctx.signing_context.ui.proto.data, 32); // check view data eq to signed data - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + if (memcmp(&tmp_ctx.signing_context.first_data_hash, &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } - os_memset(&tmp_ctx.signing_context.ui.proto, 0, + memset(&tmp_ctx.signing_context.ui.proto, 0, sizeof(tmp_ctx.signing_context.ui.proto)); - os_memset(&tmp_ctx.signing_context.ui.hash_ctx, 0, + memset(&tmp_ctx.signing_context.ui.hash_ctx, 0, sizeof(tmp_ctx.signing_context.ui.hash_ctx)); cx_blake2b_init(&tmp_ctx.signing_context.ui.hash_ctx, 256); build_protobuf_child_tx( @@ -322,11 +322,11 @@ void make_allowed_ui_steps(bool is_last) { G_io_apdu_buffer[4] - tmp_ctx.signing_context.sign_from, tmp_ctx.signing_context.data_size); } - os_memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); + memset(&tmp_ctx.signing_context.ui.proto.data, 0, 64); cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, tmp_ctx.signing_context.ui.proto.data, 32); // check view data eq to signed data - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + if (memcmp(&tmp_ctx.signing_context.first_data_hash, &tmp_ctx.signing_context.ui.proto.data, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } @@ -357,7 +357,7 @@ void make_allowed_ui_steps(bool is_last) { tmp_ctx.signing_context.ui.byte.step < 15) || (tmp_ctx.signing_context.ui.byte.step == 15 && !tmp_ctx.signing_context.ui.finished)) { - build_transfer_ui_step(is_last); + build_transfer_ui_step(); } } else { tmp_ctx.signing_context.ui.byte.step++; @@ -379,11 +379,11 @@ void make_allowed_ui_steps(bool is_last) { cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_NONE, G_io_apdu_buffer + 5 + start_index, hash_data_size, NULL, 0); if (last_hash) { - os_memset(&tmp_ctx.signing_context.ui.byte.buffer, 0, 64); + memset(&tmp_ctx.signing_context.ui.byte.buffer, 0, 64); cx_hash(&tmp_ctx.signing_context.ui.hash_ctx.header, CX_LAST, NULL, 0, tmp_ctx.signing_context.ui.byte.buffer, 32); // check view data eq to signed data - if (os_memcmp(&tmp_ctx.signing_context.first_data_hash, + if (memcmp(&tmp_ctx.signing_context.first_data_hash, &tmp_ctx.signing_context.ui.byte.buffer, 32) != 0) { THROW(SW_SIGN_DATA_NOT_MATCH); } diff --git a/src/ui/ui.h b/src/ui/ui.h index 59a28af3..e4ea8690 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -23,6 +23,7 @@ #include "os.h" #include "cx.h" +#include "ux.h" #include #include "../main.h" #include "../crypto/ledger_crypto.h" diff --git a/src/ui/ui_logic.c b/src/ui/ui_logic.c index 48e46f75..362a022a 100644 --- a/src/ui/ui_logic.c +++ b/src/ui/ui_logic.c @@ -21,6 +21,7 @@ #include "ui_logic.h" #include "main.h" #include "ui.h" +#include "ux.h" // UI unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) { diff --git a/src/ui/ui_logic.h b/src/ui/ui_logic.h index 2132344e..ab33b8d9 100644 --- a/src/ui/ui_logic.h +++ b/src/ui/ui_logic.h @@ -22,6 +22,7 @@ #define __UI_LOGIC_H__ #include "os_io_seproxyhal.h" +#include "ux.h" unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e); unsigned int io_seproxyhal_cancel(const bagl_element_t *e); From a766b0fdd996acd00e12611527e2cc04fb412b85 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Wed, 21 Jul 2021 11:00:59 +0400 Subject: [PATCH 23/26] add minor fixes --- .gitignore | 5 +- src/crypto/stream_eddsa_sign.c | 87 ++++++++++++++-------------------- src/main.c | 2 +- 3 files changed, 40 insertions(+), 54 deletions(-) diff --git a/.gitignore b/.gitignore index c57f2129..64ce1386 100644 --- a/.gitignore +++ b/.gitignore @@ -55,4 +55,7 @@ dkms.conf debug/ ledger-nanopb/ .DS_Store -*.pyc \ No newline at end of file +*.pyc +src/glyphs.c +src/glyphs.h +bin \ No newline at end of file diff --git a/src/crypto/stream_eddsa_sign.c b/src/crypto/stream_eddsa_sign.c index 24f44140..ed3a849c 100644 --- a/src/crypto/stream_eddsa_sign.c +++ b/src/crypto/stream_eddsa_sign.c @@ -22,69 +22,52 @@ #include "string.h" #include "../main.h" -static uint8_t const C_cx_Ed25519_a[] = { - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec}; +static uint8_t const C_cx_Ed25519_a[] = {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xec}; static uint8_t const C_cx_Ed25519_d[] = { // d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3 - 0x52, 0x03, 0x6c, 0xee, 0x2b, 0x6f, 0xfe, 0x73, 0x8c, 0xc7, 0x40, - 0x79, 0x77, 0x79, 0xe8, 0x98, 0x00, 0x70, 0x0a, 0x4d, 0x41, 0x41, - 0xd8, 0xab, 0x75, 0xeb, 0x4d, 0xca, 0x13, 0x59, 0x78, 0xa3}; + 0x52, 0x03, 0x6c, 0xee, 0x2b, 0x6f, 0xfe, 0x73, 0x8c, 0xc7, 0x40, 0x79, 0x77, 0x79, 0xe8, 0x98, + 0x00, 0x70, 0x0a, 0x4d, 0x41, 0x41, 0xd8, 0xab, 0x75, 0xeb, 0x4d, 0xca, 0x13, 0x59, 0x78, 0xa3}; static uint8_t const C_cx_Ed25519_q[] = { // q: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed}; + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed}; static uint8_t const C_cx_Ed25519_Hq[] = { // Hq: 0x00000000000000000000000000000000000000000000000000000000000005a4 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa4}; -static uint8_t const C_cx_Ed25519_Bx[] = { - 0x21, 0x69, 0x36, 0xd3, 0xcd, 0x6e, 0x53, 0xfe, 0xc0, 0xa4, 0xe2, - 0x31, 0xfd, 0xd6, 0xdc, 0x5c, 0x69, 0x2c, 0xc7, 0x60, 0x95, 0x25, - 0xa7, 0xb2, 0xc9, 0x56, 0x2d, 0x60, 0x8f, 0x25, 0xd5, 0x1a}; -static uint8_t const C_cx_Ed25519_By[] = { - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x58}; -static uint8_t const C_cx_Ed25519_l[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xa4}; +static uint8_t const C_cx_Ed25519_Bx[] = {0x21, 0x69, 0x36, 0xd3, 0xcd, 0x6e, 0x53, 0xfe, 0xc0, 0xa4, 0xe2, + 0x31, 0xfd, 0xd6, 0xdc, 0x5c, 0x69, 0x2c, 0xc7, 0x60, 0x95, 0x25, + 0xa7, 0xb2, 0xc9, 0x56, 0x2d, 0x60, 0x8f, 0x25, 0xd5, 0x1a}; +static uint8_t const C_cx_Ed25519_By[] = {0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x58}; +static uint8_t const C_cx_Ed25519_l[] = { // l: 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, - 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}; + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}; static uint8_t const C_cx_Ed25519_Hl[] = { // Hl: 0x0399411b7c309a3dceec73d217f5be65d00e1ba768859347a40611e3449c0f01 - 0x03, 0x99, 0x41, 0x1b, 0x7c, 0x30, 0x9a, 0x3d, 0xce, 0xec, 0x73, - 0xd2, 0x17, 0xf5, 0xbe, 0x65, 0xd0, 0x0e, 0x1b, 0xa7, 0x68, 0x85, - 0x93, 0x47, 0xa4, 0x06, 0x11, 0xe3, 0x44, 0x9c, 0x0f, 0x01}; -static uint8_t const C_cx_Ed25519_I[] = { - // I: 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0 - 0x2b, 0x83, 0x24, 0x80, 0x4f, 0xc1, 0xdf, 0x0b, 0x2b, 0x4d, 0x00, - 0x99, 0x3d, 0xfb, 0xd7, 0xa7, 0x2f, 0x43, 0x18, 0x06, 0xad, 0x2f, - 0xe4, 0x78, 0xc4, 0xee, 0x1b, 0x27, 0x4a, 0x0e, 0xa0, 0xb0}; -static uint8_t const C_cx_Ed25519_Qplus3div8[] = { - // q3: 0x0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe - 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; + 0x03, 0x99, 0x41, 0x1b, 0x7c, 0x30, 0x9a, 0x3d, 0xce, 0xec, 0x73, 0xd2, 0x17, 0xf5, 0xbe, 0x65, + 0xd0, 0x0e, 0x1b, 0xa7, 0x68, 0x85, 0x93, 0x47, 0xa4, 0x06, 0x11, 0xe3, 0x44, 0x9c, 0x0f, 0x01}; + #define C_cx_Ed25519_h 8 + cx_curve_twisted_edwards_t const C_cx_Ed25519 = { - CX_CURVE_Ed25519, - 256, - 32, - (uint8_t *)C_cx_Ed25519_q, - (uint8_t *)C_cx_Ed25519_Hq, - (uint8_t *)C_cx_Ed25519_Bx, - (uint8_t *)C_cx_Ed25519_By, - (uint8_t *)C_cx_Ed25519_l, - (uint8_t *)C_cx_Ed25519_Hl, - C_cx_Ed25519_h, - (uint8_t *)C_cx_Ed25519_a, - (uint8_t *)C_cx_Ed25519_d, - (uint8_t *)C_cx_Ed25519_I, - (uint8_t *)C_cx_Ed25519_Qplus3div8, + .curve = CX_CURVE_Ed25519, + .bit_size = 256, + .length = 32, + + .a = C_cx_Ed25519_a, + .b = C_cx_Ed25519_d, + .p = C_cx_Ed25519_q, + .Gx = C_cx_Ed25519_Bx, + .Gy = C_cx_Ed25519_By, + .n = C_cx_Ed25519_l, + .h = C_cx_Ed25519_h, + .Hp = C_cx_Ed25519_Hq, + .Hn = C_cx_Ed25519_Hl, }; /* ----------------------------------------------------------------------- */ diff --git a/src/main.c b/src/main.c index 53943e77..0eb7c083 100644 --- a/src/main.c +++ b/src/main.c @@ -219,7 +219,7 @@ void handle_apdu(volatile unsigned int *flags, volatile unsigned int *tx, BEGIN_TRY { TRY { - if (os_global_pin_is_validated() == 0) { + if (os_global_pin_is_validated() != BOLOS_UX_OK) { THROW(SW_DEVICE_IS_LOCKED); } From 9b78970baf3af329e91581b086000da1a6813325 Mon Sep 17 00:00:00 2001 From: Vladislav Petushkov Date: Thu, 22 Jul 2021 11:03:30 +0400 Subject: [PATCH 24/26] turn off printf --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a44b6fba..5fe407f7 100755 --- a/Makefile +++ b/Makefile @@ -97,7 +97,7 @@ DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF -DEBUG = 1 +DEBUG = 0 ifneq ($(DEBUG),0) ifeq ($(TARGET_NAME),TARGET_NANOX) From a4ad3cde55ac3fc2c41c4b349f7d27b1279f0125 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 20 Jul 2022 13:43:16 +0300 Subject: [PATCH 25/26] before fix --- Makefile | 36 ++++++++++++++++-------------------- src/main.c | 5 +---- 2 files changed, 17 insertions(+), 24 deletions(-) mode change 100755 => 100644 Makefile diff --git a/Makefile b/Makefile old mode 100755 new mode 100644 index 5fe407f7..d3bc6389 --- a/Makefile +++ b/Makefile @@ -24,19 +24,17 @@ include $(BOLOS_SDK)/Makefile.defines APPVERSION_M=1 APPVERSION_N=2 -APPVERSION_P=0 +APPVERSION_P=1 APPNAME = "Waves" APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) ifeq ($(TARGET_NAME),TARGET_BLUE) ICONNAME=blue_app_waves.gif +else ifeq ($(TARGET_NAME),TARGET_NANOS) +ICONNAME=nanos_app_waves.gif else - ifeq ($(TARGET_NAME),TARGET_NANOX) -ICONNAME=nanox_app_waves.gif - else -ICONNAME = nanos_app_waves.gif - endif +ICONNAME = nanox_app_waves.gif endif APP_LOAD_PARAMS = --appFlags 0x240 --path "44'/5741564'" --curve secp256k1 --curve ed25519 $(COMMON_LOAD_PARAMS) @@ -48,16 +46,11 @@ APP_SOURCE_PATH += src SDK_SOURCE_PATH += lib_stusb #qrcode #use the SDK U2F+HIDGEN USB profile SDK_SOURCE_PATH += lib_u2f lib_stusb_impl +SDK_SOURCE_PATH += lib_ux +DEFINES += HAVE_UX_FLOW ifeq ($(TARGET_NAME),TARGET_NANOX) SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl -SDK_SOURCE_PATH += lib_ux -DEFINES += HAVE_UX_FLOW -endif - -ifeq ($(TARGET_NAME),TARGET_NANOS) -SDK_SOURCE_PATH += lib_ux -DEFINES += HAVE_UX_FLOW endif DEFINES += APPVERSION=\"$(APPVERSION)\" @@ -81,30 +74,32 @@ DEFINES += MAX_DATA_SIZE=128 DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" + ifeq ($(TARGET_NAME),TARGET_NANOX) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE +endif +ifeq ($(TARGET_NAME),TARGET_NANOS) +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 +else +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_GLO096 DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX -else -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 endif # Enabling debug PRINTF DEBUG = 0 ifneq ($(DEBUG),0) - ifeq ($(TARGET_NAME),TARGET_NANOX) - DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf - DEFINES += HAVE_PRINTF_PB PRINTF_PB=mcu_usb_printf - else + ifeq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_PRINTF PRINTF=screen_printf + else + DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf endif else DEFINES += PRINTF\(...\)= @@ -156,5 +151,6 @@ include $(BOLOS_SDK)/Makefile.glyphs include $(BOLOS_SDK)/Makefile.rules + listvariants: @echo VARIANTS COIN waves diff --git a/src/main.c b/src/main.c index 0eb7c083..24ed9bc9 100644 --- a/src/main.c +++ b/src/main.c @@ -40,9 +40,6 @@ internal_storage_t const N_storage_real; // SPI Buffer for io_event unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; -#if !defined(TARGET_NANOS) && !defined(TARGET_BLUE) && !defined(TARGET_NANOX) -#error This application only supports the Ledger Nano S, Nano X and the Ledger Blue -#endif unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { @@ -550,4 +547,4 @@ __attribute__((section(".boot"))) int main(void) { } app_exit(); return 0; -} \ No newline at end of file +} From 42495d1ec7994c103409d0dbf22d839ce34dc4d0 Mon Sep 17 00:00:00 2001 From: Nikita Date: Wed, 20 Jul 2022 14:08:31 +0300 Subject: [PATCH 26/26] fix version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d3bc6389..622fdde9 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ include $(BOLOS_SDK)/Makefile.defines APPVERSION_M=1 APPVERSION_N=2 -APPVERSION_P=1 +APPVERSION_P=0 APPNAME = "Waves" APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)