Expose which keys signed the Transaction in the SDK

This commit is contained in:
Michael Vines
2018-11-29 12:32:16 -08:00
parent 0878bd53d9
commit bad0b55ab6
13 changed files with 116 additions and 39 deletions

View File

@ -110,11 +110,12 @@ SOL_FN_PREFIX bool SolPubkey_same(const SolPubkey *one, const SolPubkey *two) {
* Keyed Account
*/
typedef struct {
SolPubkey *key; /** Public Key of the account */
uint64_t *tokens; /** Numer of tokens owned by this account */
uint64_t userdata_len; /** Length of userdata in bytes */
uint8_t *userdata; /** On-chain data owned by this account */
SolPubkey *owner; /** Program that owns this account */
SolPubkey *key; /** Public key of the account */
bool is_signer; /** Transaction was signed by this account's key */
uint64_t *tokens; /** Number of tokens owned by this account */
uint64_t userdata_len; /** Length of data in bytes */
uint8_t *userdata; /** On-chain data within this account */
SolPubkey *owner; /** Program that owns this account */
} SolKeyedAccount;
/**
@ -243,6 +244,8 @@ SOL_FN_PREFIX bool sol_deserialize(
input += sizeof(uint64_t);
for (int i = 0; i < ka_len; i++) {
// key
ka[i].is_signer = *(uint64_t *) input != 0;
input += sizeof(uint64_t);
ka[i].key = (SolPubkey *) input;
input += sizeof(SolPubkey);
@ -319,6 +322,7 @@ SOL_FN_PREFIX void sol_log_params(
) {
sol_log_64(0, 0, 0, 0, ka_len);
for (int i = 0; i < ka_len; i++) {
sol_log_64(0, 0, 0, 0, ka[i].is_signer);
sol_log_key(ka[i].key);
sol_log_64(0, 0, 0, 0, *ka[i].tokens);
sol_log_array(ka[i].userdata, ka[i].userdata_len);

View File

@ -20,6 +20,11 @@ extern bool entrypoint(const uint8_t *input) {
return false;
}
if (!ka[0].is_signer) {
sol_log("Transaction not signed by key 0");
return false;
}
int64_t tokens = *(int64_t *)data;
if (*ka[0].tokens >= tokens) {
*ka[0].tokens -= tokens;

View File

@ -110,7 +110,9 @@ fn serialize_parameters(
v.write_u64::<LittleEndian>(keyed_accounts.len() as u64)
.unwrap();
for info in keyed_accounts.iter_mut() {
v.write_all(info.key.as_ref()).unwrap();
v.write_u64::<LittleEndian>(info.signer_key().is_some() as u64)
.unwrap();
v.write_all(info.unsigned_key().as_ref()).unwrap();
v.write_u64::<LittleEndian>(info.account.tokens).unwrap();
v.write_u64::<LittleEndian>(info.account.userdata.len() as u64)
.unwrap();
@ -129,6 +131,7 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) {
let mut start = mem::size_of::<u64>();
for info in keyed_accounts.iter_mut() {
start += mem::size_of::<u64>(); // skip signer_key boolean
start += mem::size_of::<Pubkey>(); // skip pubkey
info.account.tokens = LittleEndian::read_u64(&buffer[start..]);
@ -185,6 +188,10 @@ fn entrypoint(
vm.get_last_instruction_count()
);
} else if let Ok(instruction) = deserialize(tx_data) {
if keyed_accounts[0].signer_key().is_none() {
warn!("key[0] did not sign the transaction");
return false;
}
match instruction {
LoaderInstruction::Write { offset, bytes } => {
let offset = offset as usize;
@ -202,7 +209,10 @@ fn entrypoint(
}
LoaderInstruction::Finalize => {
keyed_accounts[0].account.executable = true;
info!("Finalize: account {:?}", keyed_accounts[0].key);
info!(
"Finalize: account {:?}",
keyed_accounts[0].signer_key().unwrap()
);
}
}
} else {

View File

@ -182,7 +182,7 @@ impl TokenProgram {
}
if let TokenProgram::Account(dest_account) = &input_program_accounts[1] {
if info[0].key != &dest_account.token {
if info[0].signer_key().unwrap() != &dest_account.token {
error!("account 1 token mismatch");
Err(Error::InvalidArgument)?;
}
@ -225,16 +225,15 @@ impl TokenProgram {
error!("account 0 is already allocated");
Err(Error::InvalidArgument)?;
}
let mut token_account_info = TokenAccountInfo {
token: *info[2].key,
owner: *info[1].key,
token: *info[2].unsigned_key(),
owner: *info[1].unsigned_key(),
amount: 0,
delegate: None,
};
if input_program_accounts.len() >= 4 {
token_account_info.delegate = Some(TokenAccountDelegateInfo {
source: *info[3].key,
source: *info[3].unsigned_key(),
original_amount: 0,
});
}
@ -266,7 +265,7 @@ impl TokenProgram {
Err(Error::InvalidArgument)?;
}
if info[0].key != &source_account.owner {
if info[0].signer_key().unwrap() != &source_account.owner {
error!("owner of account 1 not present");
Err(Error::InvalidArgument)?;
}
@ -291,7 +290,7 @@ impl TokenProgram {
error!("account 1/3 token mismatch");
Err(Error::InvalidArgument)?;
}
if info[3].key != &delegate_info.source {
if info[3].unsigned_key() != &delegate_info.source {
error!("Account 1 is not a delegate of account 3");
Err(Error::InvalidArgument)?;
}
@ -338,7 +337,7 @@ impl TokenProgram {
Err(Error::InvalidArgument)?;
}
if info[0].key != &source_account.owner {
if info[0].signer_key().unwrap() != &source_account.owner {
error!("owner of account 1 not present");
Err(Error::InvalidArgument)?;
}
@ -354,7 +353,7 @@ impl TokenProgram {
Err(Error::InvalidArgument)?;
}
Some(delegate_info) => {
if info[1].key != &delegate_info.source {
if info[1].unsigned_key() != &delegate_info.source {
error!("account 2 is not a delegate of account 1");
Err(Error::InvalidArgument)?;
}
@ -387,13 +386,13 @@ impl TokenProgram {
}
if let TokenProgram::Account(source_account) = &input_program_accounts[1] {
if info[0].key != &source_account.owner {
if info[0].signer_key().unwrap() != &source_account.owner {
info!("owner of account 1 not present");
Err(Error::InvalidArgument)?;
}
let mut output_source_account = source_account.clone();
output_source_account.owner = *info[2].key;
output_source_account.owner = *info[2].unsigned_key();
output_program_accounts.push((1, TokenProgram::Account(output_source_account)));
} else {
info!("account 1 is invalid");
@ -406,6 +405,10 @@ impl TokenProgram {
let command = bincode::deserialize::<Command>(input).map_err(Self::map_to_invalid_args)?;
info!("process_transaction: command={:?}", command);
if info[0].signer_key().is_none() {
Err(Error::InvalidArgument)?;
}
let input_program_accounts: Vec<TokenProgram> = info
.iter()
.map(|keyed_account| {

View File

@ -19,7 +19,14 @@ fn set_accounts(lua: &Lua, name: &str, keyed_accounts: &[KeyedAccount]) -> Resul
let accounts = lua.create_table()?;
for (i, keyed_account) in keyed_accounts.iter().enumerate() {
let account = lua.create_table()?;
account.set("key", keyed_account.key.to_string())?;
account.set(
if keyed_account.signer_key().is_some() {
"signer_key"
} else {
"unsigned_key"
},
keyed_account.unsigned_key().to_string(),
)?;
account.set("tokens", keyed_account.account.tokens)?;
let data_str = lua.create_string(&keyed_account.account.userdata)?;
account.set("userdata", data_str)?;
@ -80,6 +87,10 @@ fn entrypoint(
}
}
} else if let Ok(instruction) = deserialize(tx_data) {
if keyed_accounts[0].signer_key().is_none() {
warn!("key[0] did not sign the transaction");
return false;
}
match instruction {
LoaderInstruction::Write { offset, bytes } => {
let offset = offset as usize;
@ -98,7 +109,10 @@ fn entrypoint(
LoaderInstruction::Finalize => {
keyed_accounts[0].account.executable = true;
trace!("LuaLoader::Finalize prog: {:?}", keyed_accounts[0].key);
trace!(
"LuaLoader::Finalize prog: {:?}",
keyed_accounts[0].signer_key().unwrap()
);
}
}
} else {