-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
197 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
ifdef FD_HAS_INT128 | ||
$(call add-hdrs,fd_txn_generate.h) | ||
$(call add-objs,fd_txn_generate,fd_flamenco) | ||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
#include "fd_txn_generate.h" | ||
|
||
/* Message header type */ | ||
struct __attribute__((packed)) fd_txn_message_hdr { | ||
uchar num_signatures; | ||
uchar num_readonly_signatures; | ||
uchar num_readonly_unsigned; | ||
}; | ||
|
||
typedef struct fd_txn_message_hdr fd_txn_message_hdr_t; | ||
|
||
static fd_txn_instr_t * | ||
fd_txn_instr_meta_generate( uchar * out_buf, | ||
uchar program_id, | ||
ushort acct_cnt, | ||
ushort data_sz, | ||
ushort acct_off, | ||
ushort data_off ) { | ||
fd_txn_instr_t * out_instr = (fd_txn_instr_t *) out_buf; | ||
out_instr->program_id = program_id; | ||
out_instr->acct_cnt = acct_cnt; | ||
out_instr->data_sz = data_sz; | ||
out_instr->acct_off = acct_off; | ||
out_instr->data_off = data_off; | ||
return out_instr; | ||
} | ||
|
||
ulong | ||
fd_txn_base_generate( uchar out_txn_meta[ static FD_TXN_MAX_SZ ], | ||
uchar out_txn_payload[ static FD_TXN_MTU ], | ||
ulong num_signatures, | ||
fd_txn_accounts_t * accounts, | ||
uchar * opt_recent_blockhash ) { | ||
|
||
FD_TEST(num_signatures <= 128); | ||
*out_txn_payload = (uchar)num_signatures; | ||
/* Fill out txn metadata */ | ||
fd_txn_t * txn_meta = (fd_txn_t *) out_txn_meta; | ||
txn_meta->acct_addr_cnt = accounts->acct_cnt; | ||
txn_meta->readonly_signed_cnt = accounts->readonly_signed_cnt; | ||
txn_meta->readonly_unsigned_cnt = accounts->readonly_unsigned_cnt; | ||
/* Number of signatures is encoded as a compact u16 but | ||
can always be encoded using 1 byte here. */ | ||
txn_meta->message_off = (ushort)(num_signatures * FD_TXN_SIGNATURE_SZ + 1); | ||
txn_meta->signature_off = (ushort)1UL; | ||
txn_meta->instr_cnt = 0; | ||
|
||
FD_TEST(txn_meta->acct_addr_cnt <= 128); | ||
txn_meta->acct_addr_off = (ushort)(txn_meta->message_off + (sizeof(fd_txn_message_hdr_t)) + 1); | ||
txn_meta->recent_blockhash_off = (ushort)(txn_meta->acct_addr_off + (txn_meta->acct_addr_cnt * FD_TXN_ACCT_ADDR_SZ)); | ||
|
||
/* Fill message header in txn payload */ | ||
uchar * write_ptr = out_txn_payload + txn_meta->message_off; | ||
fd_txn_message_hdr_t msg_header = { .num_signatures = accounts->signature_cnt, | ||
.num_readonly_signatures = accounts->readonly_signed_cnt, | ||
.num_readonly_unsigned = accounts->readonly_unsigned_cnt }; | ||
memcpy( write_ptr, &msg_header, sizeof(fd_txn_message_hdr_t) ) ; | ||
write_ptr += sizeof(fd_txn_message_hdr_t); | ||
|
||
/* Write number of accounts */ | ||
*write_ptr = (uchar)txn_meta->acct_addr_cnt; | ||
write_ptr += 1; | ||
|
||
/* Write accounts list to txn payload */ | ||
ulong signers_write_sz = FD_TXN_ACCT_ADDR_SZ * (accounts->signature_cnt - accounts->readonly_signed_cnt); | ||
fd_memcpy( write_ptr, accounts->signers_w, signers_write_sz ); | ||
write_ptr += signers_write_sz; | ||
|
||
fd_memcpy( write_ptr, accounts->signers_r, FD_TXN_ACCT_ADDR_SZ * accounts->readonly_signed_cnt ); | ||
write_ptr += FD_TXN_ACCT_ADDR_SZ * accounts->readonly_signed_cnt; | ||
|
||
ulong non_signers_write_sz = FD_TXN_ACCT_ADDR_SZ * (ulong)(accounts->acct_cnt - accounts->readonly_unsigned_cnt - accounts->signature_cnt); | ||
fd_memcpy( write_ptr, accounts->non_signers_w, non_signers_write_sz); | ||
write_ptr += non_signers_write_sz; | ||
|
||
fd_memcpy( write_ptr, accounts->non_signers_r, FD_TXN_ACCT_ADDR_SZ * accounts->readonly_unsigned_cnt ); | ||
write_ptr += FD_TXN_ACCT_ADDR_SZ * accounts->readonly_unsigned_cnt; | ||
FD_TEST( (ushort)((ulong)write_ptr - (ulong)out_txn_payload) == txn_meta->recent_blockhash_off ); | ||
|
||
/* Write recent blockhash */ | ||
if( FD_LIKELY( opt_recent_blockhash ) ) { | ||
memcpy( write_ptr, opt_recent_blockhash, FD_TXN_BLOCKHASH_SZ ); | ||
} else { | ||
memset( write_ptr, 0UL, FD_TXN_BLOCKHASH_SZ ); | ||
} | ||
write_ptr += FD_TXN_BLOCKHASH_SZ; | ||
|
||
return (ulong)(write_ptr - out_txn_payload); | ||
} | ||
|
||
ulong | ||
fd_txn_add_instr( uchar * txn_meta_ptr, | ||
uchar out_txn_payload[ static FD_TXN_MTU ], | ||
uchar program_id, | ||
uchar const * accounts, | ||
ulong accounts_sz, | ||
uchar const * instr_buf, | ||
ulong instr_buf_sz ) { | ||
|
||
fd_txn_t * txn_meta = (fd_txn_t *) txn_meta_ptr; | ||
FD_TEST( txn_meta->instr_cnt < FD_TXN_INSTR_MAX ); | ||
FD_TEST( txn_meta->recent_blockhash_off != 0 ); | ||
|
||
uchar * instr_start = out_txn_payload + txn_meta->recent_blockhash_off + FD_TXN_BLOCKHASH_SZ; | ||
txn_meta->instr_cnt++; | ||
uchar * write_ptr = instr_start; | ||
|
||
uchar compact_instr_cnt_sz = (uchar) fd_cu16_enc( (ushort)txn_meta->instr_cnt, write_ptr ); | ||
FD_TEST( compact_instr_cnt_sz == 1 ); | ||
|
||
write_ptr += compact_instr_cnt_sz; | ||
|
||
/* Calculate offset of next instruction. */ | ||
if ( txn_meta->instr_cnt > 1 ) { | ||
write_ptr = out_txn_payload + txn_meta->instr[txn_meta->instr_cnt-2].data_off + txn_meta->instr[txn_meta->instr_cnt-2].data_sz; | ||
} | ||
|
||
instr_start = write_ptr; | ||
|
||
*write_ptr = program_id; | ||
write_ptr += sizeof(uchar); | ||
|
||
uchar compact_accts_len_sz = (uchar) fd_cu16_enc( (ushort)accounts_sz, write_ptr ); | ||
write_ptr += compact_accts_len_sz; | ||
|
||
fd_memcpy( write_ptr, accounts, accounts_sz ); | ||
write_ptr += accounts_sz; | ||
|
||
ushort data_sz = (ushort)instr_buf_sz; | ||
uint compact_data_len_sz = fd_cu16_enc( data_sz, write_ptr ); | ||
write_ptr += compact_data_len_sz; | ||
|
||
/* Copy data buffer over */ | ||
ushort data_off = (ushort) (write_ptr - out_txn_payload); | ||
fd_memcpy( write_ptr, instr_buf, data_sz ); | ||
write_ptr += data_sz; | ||
ushort acct_off = (ushort) (instr_start + sizeof(uchar) + compact_accts_len_sz - out_txn_payload); | ||
|
||
(void) fd_txn_instr_meta_generate( (uchar*)&txn_meta->instr[txn_meta->instr_cnt-1], | ||
program_id, | ||
(ushort)accounts_sz, | ||
data_sz, acct_off, data_off ); | ||
return (ulong)(write_ptr - out_txn_payload); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* Provides utility methods to create txn templates for | ||
pre-staging, as well as a mechanism to build out an | ||
entire transaction with instructions. */ | ||
|
||
#include "../../ballet/txn/fd_txn.h" | ||
#include "../../ballet/txn/fd_compact_u16.h" | ||
#include "../../flamenco/types/fd_types_custom.h" | ||
#include "../../flamenco/types/fd_types.h" | ||
|
||
/* Struct used to define a list of accounts supplied in a txn. | ||
Also provides information on number of signers/writeable accounts. */ | ||
struct fd_txn_accounts { | ||
/* signature cnt <= 256 */ | ||
uchar signature_cnt; | ||
/* readonly signed/unsigned <= 256 */ | ||
uchar readonly_signed_cnt; | ||
uchar readonly_unsigned_cnt; | ||
ushort acct_cnt; | ||
fd_pubkey_t * signers_w; | ||
fd_pubkey_t * signers_r; | ||
fd_pubkey_t * non_signers_w; | ||
fd_pubkey_t * non_signers_r; | ||
}; | ||
|
||
typedef struct fd_txn_accounts fd_txn_accounts_t; | ||
|
||
FD_PROTOTYPES_BEGIN | ||
|
||
/* Method used to create a template for a txn (useful for pre-staging and re-use) */ | ||
ulong | ||
fd_txn_base_generate( uchar out_txn_meta[ static FD_TXN_MAX_SZ ], | ||
uchar out_txn_payload[ static FD_TXN_MTU ], | ||
ulong num_signatures, | ||
fd_txn_accounts_t * accounts, | ||
uchar * opt_recent_blockhash ); | ||
|
||
/* Method used for adding an instruction to a txn being generated. | ||
The accounts param is a list of indices to the accounts in the txn. | ||
The instruction buffer contains the data for the instruction to | ||
be added. */ | ||
ulong | ||
fd_txn_add_instr( uchar * txn_meta_ptr, | ||
uchar out_txn_payload[ static FD_TXN_MTU ], | ||
uchar program_id, | ||
uchar const * accounts, | ||
ulong accounts_sz, | ||
uchar const * instr_buf, | ||
ulong instr_buf_sz ); | ||
FD_PROTOTYPES_END |