Rename userdata to data (#3282)

* Rename userdata to data

Instead of saying "userdata", which is ambiguous and imprecise,
say "instruction data" or "account data".

Also, add `ProgramError::InvalidInstructionData`

Fixes #2761
This commit is contained in:
Greg Fitzgerald 2019-03-14 10:48:27 -06:00 committed by GitHub
parent de13082347
commit c1eec0290e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 245 additions and 254 deletions

View File

@ -124,7 +124,7 @@ The result field will be a JSON object with the following sub fields:
* `lamports`, number of lamports assigned to this account, as a signed 64-bit integer
* `owner`, array of 32 bytes representing the program this account has been assigned to
* `userdata`, array of bytes representing any userdata associated with the account
* `data`, array of bytes representing any data associated with the account
* `executable`, boolean indicating if the account contains a program (and is strictly read-only)
* `loader`, array of 32 bytes representing the loader for this program (if `executable`), otherwise all
@ -134,7 +134,7 @@ The result field will be a JSON object with the following sub fields:
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getAccountInfo", "params":["2gVkYWexTHR5Hb2aLeQN3tnngvWzisFKXDUPrgMHpdST"]}' http://localhost:8899
// Result
{"jsonrpc":"2.0","result":{"executable":false,"loader":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"userdata":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"id":1}
{"jsonrpc":"2.0","result":{"executable":false,"loader":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"id":1}
```
---
@ -254,7 +254,7 @@ After connect to the RPC PubSub websocket at `ws://<ADDRESS>/`:
---
### accountSubscribe
Subscribe to an account to receive notifications when the lamports or userdata
Subscribe to an account to receive notifications when the lamports or data
for a given account public key changes
##### Parameters:
@ -274,7 +274,7 @@ for a given account public key changes
##### Notification Format:
```bash
{"jsonrpc": "2.0","method": "accountNotification", "params": {"result": {"executable":false,"loader":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"userdata":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"subscription":0}}
{"jsonrpc": "2.0","method": "accountNotification", "params": {"result": {"executable":false,"loader":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"owner":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"lamports":1,"data":[3,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,53,48,45,48,49,45,48,49,84,48,48,58,48,48,58,48,48,90,252,10,7,28,246,140,88,177,98,82,10,227,89,81,18,30,194,101,199,16,11,73,133,20,246,62,114,39,20,113,189,32,50,0,0,0,0,0,0,0,247,15,36,102,167,83,225,42,133,127,82,34,36,224,207,130,109,230,224,188,163,33,213,13,5,117,211,251,65,159,197,51,0,0,0,0,0,0]},"subscription":0}}
```
---
@ -300,7 +300,7 @@ Unsubscribe from account change notifications
---
### programSubscribe
Subscribe to a program to receive notifications when the lamports or userdata
Subscribe to a program to receive notifications when the lamports or data
for a given account owned by the program changes
##### Parameters:
@ -322,7 +322,7 @@ for a given account owned by the program changes
* `string` - account Pubkey, as base-58 encoded string
* `object` - account info JSON object (see [getAccountInfo](#getaccountinfo) for field details)
```bash
{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM",{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"userdata":[1,1,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,49,56,45,49,50,45,50,52,84,50,51,58,53,57,58,48,48,90,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,55,89,0,0,0,0,50,0,0,0,0,0,0,0,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,45,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],"subscription":0}}
{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["8Rshv2oMkPu5E4opXTRyuyBeZBqQ4S477VG26wUTFxUM",{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"data":[1,1,1,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,50,48,49,56,45,49,50,45,50,52,84,50,51,58,53,57,58,48,48,90,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,55,89,0,0,0,0,50,0,0,0,0,0,0,0,235,233,39,152,15,44,117,176,41,89,100,86,45,61,2,44,251,46,212,37,35,118,163,189,247,84,27,235,178,62,45,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}],"subscription":0}}
```
---

View File

@ -40,7 +40,7 @@ retransmitted twice around the network.
4. CrdsValue for vote should look like this ``` Votes(Vec<Transaction>) ```
Each vote transaction should maintain a `wallclock` in its userdata. The merge
Each vote transaction should maintain a `wallclock` in its data. The merge
strategy for Votes will keep the last N set of votes as configured by the local
client. For push/pull the vector is traversed recursively and each Transaction
is treated as an individual CrdsValue with its own local wallclock and

View File

@ -6,7 +6,7 @@ separating program code from the state it operates on, the runtime is able to
choreograph concurrent access. Transactions accessing only credit-only
accounts are executed in parallel whereas transactions accessing writable
accounts are serialized. The runtime interacts with the program through an
entrypoint with a well-defined interface. The userdata stored in an account is
entrypoint with a well-defined interface. The data stored in an account is
an opaque type, an array of bytes. The program has full control over its
contents.
@ -42,7 +42,7 @@ programs can be executed in parallel.
The runtime enforces the following rules:
1. Only the *owner* program may modify the contents of an account. This means
that upon assignment userdata vector is guaranteed to be zero.
that upon assignment data vector is guaranteed to be zero.
2. Total balances on all the accounts is equal before and after execution of a
transaction.
@ -59,11 +59,11 @@ accounts.
## SystemProgram Interface
The interface is best described by the `Instruction::userdata` that the user
The interface is best described by the `Instruction::data` that the user
encodes.
* `CreateAccount` - This allows the user to create an account with an allocated
userdata array and assign it to a Program.
data array and assign it to a Program.
* `Assign` - Allows the user to assign an existing account to a program.
@ -73,10 +73,10 @@ userdata array and assign it to a Program.
For blockchain to function correctly, the program code must be resilient to user
inputs. That is why in this design the program specific code is the only code
that can change the state of the userdata byte array in the Accounts that are
that can change the state of the data byte array in the Accounts that are
assigned to it. It is also the reason why `Assign` or `CreateAccount` must zero
out the userdata. Otherwise there would be no possible way for the program to
distinguish the recently assigned account userdata from a natively generated
out the data. Otherwise there would be no possible way for the program to
distinguish the recently assigned account data from a natively generated
state transition without some additional metadata from the runtime to indicate
that this memory is assigned instead of natively generated.
@ -94,12 +94,12 @@ instruction can be composed into a single transaction with the call to the
program itself.
* `CreateAccount` and `Assign` guarantee that when account is assigned to the
program, the Account's userdata is zero initialized.
program, the Account's data is zero initialized.
* Once assigned to program an Account cannot be reassigned.
* Runtime guarantees that a program's code is the only code that can modify
Account userdata that the Account is assigned to.
Account data that the Account is assigned to.
* Runtime guarantees that the program can only spend lamports that are in
accounts that are assigned to it.

View File

@ -142,7 +142,7 @@ impl ThinClient {
result
}
pub fn get_account_userdata(&mut self, pubkey: &Pubkey) -> io::Result<Option<Vec<u8>>> {
pub fn get_account_data(&mut self, pubkey: &Pubkey) -> io::Result<Option<Vec<u8>>> {
let params = json!([format!("{}", pubkey)]);
let response =
self.rpc_client
@ -151,13 +151,13 @@ impl ThinClient {
Ok(account_json) => {
let account: Account =
serde_json::from_value(account_json).expect("deserialize account");
Ok(Some(account.userdata))
Ok(Some(account.data))
}
Err(error) => {
debug!("get_account_userdata failed: {:?}", error);
debug!("get_account_data failed: {:?}", error);
Err(io::Error::new(
io::ErrorKind::Other,
"get_account_userdata failed",
"get_account_data failed",
))
}
}

View File

@ -68,7 +68,7 @@ impl CrdsValueLabel {
}
impl Vote {
// TODO: it might make sense for the transaction to encode the wallclock in the userdata
// TODO: it might make sense for the transaction to encode the wallclock in the data
pub fn new(transaction: Transaction, wallclock: u64) -> Self {
Vote {
transaction,

View File

@ -33,7 +33,7 @@ impl LeaderConfirmationService {
// the vote states
bank.vote_accounts().for_each(|(_, account)| {
total_stake += account.lamports;
let vote_state = VoteState::deserialize(&account.userdata).unwrap();
let vote_state = VoteState::deserialize(&account.data).unwrap();
if let Some(stake_and_state) = vote_state
.votes
.back()

View File

@ -187,7 +187,7 @@ impl LocalCluster {
}
info!("Checking for vote account registration");
let vote_account_user_data = client.get_account_userdata(&vote_account_pubkey);
let vote_account_user_data = client.get_account_data(&vote_account_pubkey);
if let Ok(Some(vote_account_user_data)) = vote_account_user_data {
if let Ok(vote_state) = VoteState::deserialize(&vote_account_user_data) {
if vote_state.delegate_id == delegate_id {

View File

@ -517,7 +517,7 @@ mod tests {
"result":{
"owner": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
"lamports": 20,
"userdata": [],
"data": [],
"executable": false
},
"id":1}

View File

@ -17,7 +17,7 @@ use std::sync::{atomic, Arc};
pub trait RpcSolPubSub {
type Metadata;
// Get notification every time account userdata is changed
// Get notification every time account data is changed
// Accepts pubkey parameter as base-58 encoded string
#[pubsub(
subscription = "accountNotification",
@ -34,7 +34,7 @@ pub trait RpcSolPubSub {
)]
fn account_unsubscribe(&self, _: Option<Self::Metadata>, _: SubscriptionId) -> Result<bool>;
// Get notification every time account userdata owned by a particular program is changed
// Get notification every time account data owned by a particular program is changed
// Accepts pubkey parameter as base-58 encoded string
#[pubsub(
subscription = "programNotification",
@ -371,10 +371,7 @@ mod tests {
// Test signature confirmation notification #1
let string = receiver.poll();
let expected_userdata = arc_bank
.get_account(&contract_state.pubkey())
.unwrap()
.userdata;
let expected_data = arc_bank.get_account(&contract_state.pubkey()).unwrap().data;
let expected = json!({
"jsonrpc": "2.0",
"method": "accountNotification",
@ -382,7 +379,7 @@ mod tests {
"result": {
"owner": budget_program_id,
"lamports": 51,
"userdata": expected_userdata,
"data": expected_data,
"executable": executable,
},
"subscription": 0,

View File

@ -239,7 +239,7 @@ mod tests {
subscriptions.check_account(&alice.pubkey(), &account);
let string = transport_receiver.poll();
if let Async::Ready(Some(response)) = string.unwrap() {
let expected = format!(r#"{{"jsonrpc":"2.0","method":"accountNotification","params":{{"result":{{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"userdata":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},"subscription":0}}}}"#);
let expected = format!(r#"{{"jsonrpc":"2.0","method":"accountNotification","params":{{"result":{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},"subscription":0}}}}"#);
assert_eq!(expected, response);
}
@ -285,7 +285,7 @@ mod tests {
subscriptions.check_program(&solana_budget_api::id(), &alice.pubkey(), &account);
let string = transport_receiver.poll();
if let Async::Ready(Some(response)) = string.unwrap() {
let expected = format!(r#"{{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["{:?}",{{"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"userdata":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}],"subscription":0}}}}"#, alice.pubkey());
let expected = format!(r#"{{"jsonrpc":"2.0","method":"programNotification","params":{{"result":["{:?}",{{"data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"executable":false,"lamports":1,"owner":[129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}],"subscription":0}}}}"#, alice.pubkey());
assert_eq!(expected, response);
}

View File

@ -395,10 +395,10 @@ mod tests {
}
#[test]
fn test_system_transaction_userdata_layout() {
fn test_system_transaction_data_layout() {
use crate::packet::PACKET_DATA_SIZE;
let mut tx0 = test_tx();
tx0.instructions[0].userdata = vec![1, 2, 3];
tx0.instructions[0].data = vec![1, 2, 3];
let message0a = tx0.message();
let tx_bytes = serialize(&tx0).unwrap();
assert!(tx_bytes.len() < PACKET_DATA_SIZE);
@ -408,9 +408,9 @@ mod tests {
);
let tx1 = deserialize(&tx_bytes).unwrap();
assert_eq!(tx0, tx1);
assert_eq!(tx1.instructions[0].userdata, vec![1, 2, 3]);
assert_eq!(tx1.instructions[0].data, vec![1, 2, 3]);
tx0.instructions[0].userdata = vec![1, 2, 4];
tx0.instructions[0].data = vec![1, 2, 4];
let message0b = tx0.message();
assert_ne!(message0a, message0b);
}

View File

@ -73,7 +73,7 @@ fn node_staked_accounts_at_epoch(
}
fn filter_no_delegate(account_id: &Pubkey, account: &Account) -> bool {
VoteState::deserialize(&account.userdata)
VoteState::deserialize(&account.data)
.map(|vote_state| vote_state.delegate_id != *account_id)
.unwrap_or(false)
}
@ -91,7 +91,7 @@ fn to_vote_state(
node_staked_accounts: impl Iterator<Item = (impl Borrow<Pubkey>, u64, impl Borrow<Account>)>,
) -> impl Iterator<Item = (u64, VoteState)> {
node_staked_accounts.filter_map(|(_, stake, account)| {
VoteState::deserialize(&account.borrow().userdata)
VoteState::deserialize(&account.borrow().data)
.ok()
.map(|vote_state| (stake, vote_state))
})

View File

@ -235,7 +235,7 @@ impl StorageStage {
);
if let Some(account) = account_to_create {
if client.get_account_userdata(&account).is_ok() {
if client.get_account_data(&account).is_ok() {
return Ok(());
}
}
@ -383,7 +383,7 @@ impl StorageStage {
*current_key_idx += size_of::<Signature>();
*current_key_idx %= storage_keys.len();
} else if solana_storage_api::check_id(&program_id) {
match deserialize(&tx.instructions[i].userdata) {
match deserialize(&tx.instructions[i].data) {
Ok(StorageProgram::SubmitMiningProof {
entry_height: proof_entry_height,
..

View File

@ -372,7 +372,7 @@ mod tests {
assert_eq!(tx.program_ids, vec![system_program::id()]);
assert_eq!(tx.instructions.len(), 1);
let instruction: SystemInstruction = deserialize(&tx.instructions[0].userdata).unwrap();
let instruction: SystemInstruction = deserialize(&tx.instructions[0].data).unwrap();
assert_eq!(
instruction,
SystemInstruction::CreateAccount {

View File

@ -123,8 +123,8 @@ pub fn sol_log_params(ka: &[SolKeyedAccount], data: &[u8]) {
sol_log_key(&k.key);
sol_log("- Lamports");
sol_log_64(0, 0, 0, 0, k.lamports);
sol_log("- Userdata");
sol_log_slice(k.userdata);
sol_log("- AccountData");
sol_log_slice(k.data);
sol_log("- Owner");
sol_log_key(&k.owner);
}
@ -148,7 +148,7 @@ pub struct SolKeyedAccount<'a> {
/// Number of lamports owned by this account
pub lamports: u64,
/// On-chain data within this account
pub userdata: &'a [u8],
pub data: &'a [u8],
/// Program that owns this account
pub owner: SolPubkey<'a>,
}
@ -200,15 +200,15 @@ pub extern "C" fn entrypoint(input: *mut u8) -> bool {
};
offset += size_of::<u64>();
let userdata_length = unsafe {
let data_length = unsafe {
#[allow(clippy::cast_ptr_alignment)]
let userdata_length_ptr: *const u64 = input.add(offset) as *const u64;
*userdata_length_ptr
let data_length_ptr: *const u64 = input.add(offset) as *const u64;
*data_length_ptr
} as usize;
offset += size_of::<u64>();
let userdata = unsafe { from_raw_parts(input.add(offset), userdata_length) };
offset += userdata_length;
let data = unsafe { from_raw_parts(input.add(offset), data_length) };
offset += data_length;
let owner_slice = unsafe { from_raw_parts(input.add(offset), SIZE_PUBKEY) };
let owner = SolPubkey { key: &owner_slice };
@ -218,7 +218,7 @@ pub extern "C" fn entrypoint(input: *mut u8) -> bool {
key,
is_signer,
lamports,
userdata,
data,
owner,
}];
@ -386,7 +386,7 @@ mod tests {
assert_eq!(SIZE_PUBKEY, ka[0].key.key.len());
assert_eq!(key, ka[0].key.key);
assert_eq!(48, ka[0].lamports);
assert_eq!(1, ka[0].userdata.len());
assert_eq!(1, ka[0].data.len());
let owner = [0; 32];
assert_eq!(SIZE_PUBKEY, ka[0].owner.key.len());
assert_eq!(owner, ka[0].owner.key);

View File

@ -148,9 +148,9 @@ fn serialize_parameters(
.unwrap();
v.write_all(info.unsigned_key().as_ref()).unwrap();
v.write_u64::<LittleEndian>(info.account.lamports).unwrap();
v.write_u64::<LittleEndian>(info.account.userdata.len() as u64)
v.write_u64::<LittleEndian>(info.account.data.len() as u64)
.unwrap();
v.write_all(&info.account.userdata).unwrap();
v.write_all(&info.account.data).unwrap();
v.write_all(info.account.owner.as_ref()).unwrap();
}
v.write_u64::<LittleEndian>(data.len() as u64).unwrap();
@ -171,10 +171,10 @@ fn deserialize_parameters(keyed_accounts: &mut [KeyedAccount], buffer: &[u8]) {
start += mem::size_of::<u64>() // skip lamports
+ mem::size_of::<u64>(); // skip length tag
let end = start + info.account.userdata.len();
info.account.userdata.clone_from_slice(&buffer[start..end]);
let end = start + info.account.data.len();
info.account.data.clone_from_slice(&buffer[start..end]);
start += info.account.userdata.len() // skip userdata
start += info.account.data.len() // skip data
+ mem::size_of::<Pubkey>(); // skip owner
}
}
@ -190,7 +190,7 @@ fn entrypoint(
if keyed_accounts[0].account.executable {
let (progs, params) = keyed_accounts.split_at_mut(1);
let prog = &progs[0].account.userdata;
let prog = &progs[0].account.data;
info!("Call BPF program");
//dump_program(keyed_accounts[0].key, prog);
let mut vm = match create_vm(prog) {
@ -228,15 +228,15 @@ fn entrypoint(
let offset = offset as usize;
let len = bytes.len();
debug!("Write: offset={} length={}", offset, len);
if keyed_accounts[0].account.userdata.len() < offset + len {
if keyed_accounts[0].account.data.len() < offset + len {
warn!(
"Write overflow: {} < {}",
keyed_accounts[0].account.userdata.len(),
keyed_accounts[0].account.data.len(),
offset + len
);
return Err(ProgramError::GenericError);
}
keyed_accounts[0].account.userdata[offset..offset + len].copy_from_slice(&bytes);
keyed_accounts[0].account.data[offset..offset + len].copy_from_slice(&bytes);
}
LoaderInstruction::Finalize => {
keyed_accounts[0].account.executable = true;

View File

@ -87,7 +87,7 @@ fn apply_debits(
keyed_accounts[0].account.lamports += payment.lamports;
Ok(())
} else {
let existing = BudgetState::deserialize(&keyed_accounts[0].account.userdata).ok();
let existing = BudgetState::deserialize(&keyed_accounts[0].account.data).ok();
if Some(true) == existing.map(|x| x.initialized) {
trace!("contract already exists");
Err(BudgetError::ContractAlreadyExists)
@ -95,13 +95,12 @@ fn apply_debits(
let mut budget_state = BudgetState::default();
budget_state.pending_budget = Some(expr);
budget_state.initialized = true;
budget_state.serialize(&mut keyed_accounts[0].account.userdata)
budget_state.serialize(&mut keyed_accounts[0].account.data)
}
}
}
BudgetInstruction::ApplyTimestamp(dt) => {
if let Ok(mut budget_state) =
BudgetState::deserialize(&keyed_accounts[1].account.userdata)
if let Ok(mut budget_state) = BudgetState::deserialize(&keyed_accounts[1].account.data)
{
if !budget_state.is_pending() {
Err(BudgetError::ContractNotPending)
@ -112,15 +111,14 @@ fn apply_debits(
trace!("apply timestamp");
apply_timestamp(&mut budget_state, keyed_accounts, *dt)?;
trace!("apply timestamp committed");
budget_state.serialize(&mut keyed_accounts[1].account.userdata)
budget_state.serialize(&mut keyed_accounts[1].account.data)
}
} else {
Err(BudgetError::UninitializedContract)
}
}
BudgetInstruction::ApplySignature => {
if let Ok(mut budget_state) =
BudgetState::deserialize(&keyed_accounts[1].account.userdata)
if let Ok(mut budget_state) = BudgetState::deserialize(&keyed_accounts[1].account.data)
{
if !budget_state.is_pending() {
Err(BudgetError::ContractNotPending)
@ -131,7 +129,7 @@ fn apply_debits(
trace!("apply signature");
apply_signature(&mut budget_state, keyed_accounts)?;
trace!("apply signature committed");
budget_state.serialize(&mut keyed_accounts[1].account.userdata)
budget_state.serialize(&mut keyed_accounts[1].account.data)
}
} else {
Err(BudgetError::UninitializedContract)
@ -146,8 +144,8 @@ pub fn process_instruction(
data: &[u8],
) -> Result<(), BudgetError> {
let instruction = deserialize(data).map_err(|err| {
info!("Invalid transaction userdata: {:?} {:?}", data, err);
BudgetError::UserdataDeserializeFailure
info!("Invalid transaction data: {:?} {:?}", data, err);
BudgetError::AccountDataDeserializeFailure
})?;
trace!("process_instruction: {:?}", instruction);
@ -178,12 +176,12 @@ mod test {
let mut accounts = vec![Account::new(1, 0, &id()), Account::new(0, 512, &id())];
let from = Keypair::new();
let contract = Keypair::new();
let userdata = (1u8, 2u8, 3u8);
let data = (1u8, 2u8, 3u8);
let tx = Transaction::new(
&from,
&[contract.pubkey()],
&id(),
&userdata,
&data,
Hash::default(),
0,
);
@ -285,7 +283,7 @@ mod test {
process_transaction(&tx, &mut accounts).unwrap();
assert_eq!(accounts[from_account].lamports, 0);
assert_eq!(accounts[contract_account].lamports, 1);
let budget_state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
let budget_state = BudgetState::deserialize(&accounts[contract_account].data).unwrap();
assert!(budget_state.is_pending());
// Attack! Try to payout to a rando key
@ -304,7 +302,7 @@ mod test {
assert_eq!(accounts[contract_account].lamports, 1);
assert_eq!(accounts[to_account].lamports, 0);
let budget_state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
let budget_state = BudgetState::deserialize(&accounts[contract_account].data).unwrap();
assert!(budget_state.is_pending());
// Now, acknowledge the time in the condition occurred and
@ -321,7 +319,7 @@ mod test {
assert_eq!(accounts[contract_account].lamports, 0);
assert_eq!(accounts[to_account].lamports, 1);
let budget_state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
let budget_state = BudgetState::deserialize(&accounts[contract_account].data).unwrap();
assert!(!budget_state.is_pending());
// try to replay the timestamp contract
@ -356,7 +354,7 @@ mod test {
process_transaction(&tx, &mut accounts).unwrap();
assert_eq!(accounts[from_account].lamports, 0);
assert_eq!(accounts[contract_account].lamports, 1);
let budget_state = BudgetState::deserialize(&accounts[contract_account].userdata).unwrap();
let budget_state = BudgetState::deserialize(&accounts[contract_account].data).unwrap();
assert!(budget_state.is_pending());
// Attack! try to put the lamports into the wrong account with cancel

View File

@ -12,8 +12,8 @@ pub enum BudgetError {
UninitializedContract,
DestinationMissing,
FailedWitness,
UserdataTooSmall,
UserdataDeserializeFailure,
AccountDataTooSmall,
AccountDataDeserializeFailure,
UnsignedKey,
}
@ -37,7 +37,7 @@ impl BudgetState {
pub fn serialize(&self, output: &mut [u8]) -> Result<(), BudgetError> {
serialize_into(output, self).map_err(|err| match *err {
_ => BudgetError::UserdataTooSmall,
_ => BudgetError::AccountDataTooSmall,
})
}
@ -56,18 +56,18 @@ mod test {
fn test_serializer() {
let mut a = Account::new(0, 512, &id());
let b = BudgetState::default();
b.serialize(&mut a.userdata).unwrap();
let c = BudgetState::deserialize(&a.userdata).unwrap();
b.serialize(&mut a.data).unwrap();
let c = BudgetState::deserialize(&a.data).unwrap();
assert_eq!(b, c);
}
#[test]
fn test_serializer_userdata_too_small() {
fn test_serializer_data_too_small() {
let mut a = Account::new(0, 1, &id());
let b = BudgetState::default();
assert_eq!(
b.serialize(&mut a.userdata),
Err(BudgetError::UserdataTooSmall)
b.serialize(&mut a.data),
Err(BudgetError::AccountDataTooSmall)
);
}
}

View File

@ -151,11 +151,11 @@ impl BudgetTransaction {
}
pub fn system_instruction(tx: &Transaction, index: usize) -> Option<SystemInstruction> {
deserialize(&tx.userdata(index)).ok()
deserialize(&tx.data(index)).ok()
}
pub fn instruction(tx: &Transaction, index: usize) -> Option<BudgetInstruction> {
deserialize(&tx.userdata(index)).ok()
deserialize(&tx.data(index)).ok()
}
/// Verify only the payment plan.
@ -236,9 +236,9 @@ mod tests {
payment.lamports = *lamports; // <-- attack, part 2!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();
tx.instructions[1].data = serialize(&instruction).unwrap();
}
tx.instructions[0].userdata = serialize(&system_instruction).unwrap();
tx.instructions[0].data = serialize(&system_instruction).unwrap();
assert!(BudgetTransaction::verify_plan(&tx));
assert!(!tx.verify_signature());
}
@ -257,7 +257,7 @@ mod tests {
payment.to = thief_keypair.pubkey(); // <-- attack!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();
tx.instructions[1].data = serialize(&instruction).unwrap();
assert!(BudgetTransaction::verify_plan(&tx));
assert!(!tx.verify_signature());
}
@ -274,7 +274,7 @@ mod tests {
payment.lamports = 2; // <-- attack!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();
tx.instructions[1].data = serialize(&instruction).unwrap();
assert!(!BudgetTransaction::verify_plan(&tx));
// Also, ensure all branchs of the plan spend all lamports
@ -284,7 +284,7 @@ mod tests {
payment.lamports = 0; // <-- whoops!
}
}
tx.instructions[1].userdata = serialize(&instruction).unwrap();
tx.instructions[1].data = serialize(&instruction).unwrap();
assert!(!BudgetTransaction::verify_plan(&tx));
}
}

View File

@ -44,7 +44,7 @@ fn redeem_vote_credits(keyed_accounts: &mut [KeyedAccount]) -> Result<(), Progra
// VoteInstruction::ClearCredits and that it points to the same vote account
// as keyed_accounts[0].
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?;
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.data)?;
// TODO: This assumes the stake is static. If not, it should use the account value
// at the time of voting, not at credit redemption.
@ -75,7 +75,7 @@ fn entrypoint(
trace!("process_instruction: {:?}", data);
trace!("keyed_accounts: {:?}", keyed_accounts);
match deserialize(data).map_err(|_| ProgramError::InvalidUserdata)? {
match deserialize(data).map_err(|_| ProgramError::InvalidInstructionData)? {
RewardsInstruction::RedeemVoteCredits => redeem_vote_credits(keyed_accounts),
}
}

View File

@ -52,7 +52,7 @@ impl<'a> RewardsBank<'a> {
self.bank.register_tick(&hash(blockhash.as_ref()));
let vote_account = self.bank.get_account(&vote_keypair.pubkey()).unwrap();
Ok(VoteState::deserialize(&vote_account.userdata).unwrap())
Ok(VoteState::deserialize(&vote_account.data).unwrap())
}
fn redeem_credits(&self, rewards_id: &Pubkey, vote_keypair: &Keypair) -> Result<VoteState> {
@ -60,7 +60,7 @@ impl<'a> RewardsBank<'a> {
let tx = RewardsTransaction::new_redeem_credits(&vote_keypair, rewards_id, blockhash, 0);
self.bank.process_transaction(&tx)?;
let vote_account = self.bank.get_account(&vote_keypair.pubkey()).unwrap();
Ok(VoteState::deserialize(&vote_account.userdata).unwrap())
Ok(VoteState::deserialize(&vote_account.data).unwrap())
}
}

View File

@ -35,7 +35,7 @@ fn entrypoint(
if keyed_accounts.len() != 1 {
// keyed_accounts[1] should be the main storage key
// to access its userdata
// to access its data
Err(ProgramError::InvalidArgument)?;
}
@ -47,7 +47,7 @@ fn entrypoint(
if let Ok(syscall) = bincode::deserialize(data) {
let mut storage_account_state = if let Ok(storage_account_state) =
bincode::deserialize(&keyed_accounts[0].account.userdata)
bincode::deserialize(&keyed_accounts[0].account.data)
{
storage_account_state
} else {
@ -159,18 +159,18 @@ fn entrypoint(
}
if bincode::serialize_into(
&mut keyed_accounts[0].account.userdata[..],
&mut keyed_accounts[0].account.data[..],
&storage_account_state,
)
.is_err()
{
return Err(ProgramError::UserdataTooSmall);
return Err(ProgramError::AccountDataTooSmall);
}
Ok(())
} else {
info!("Invalid instruction userdata: {:?}", data);
Err(ProgramError::InvalidUserdata)
info!("Invalid instruction data: {:?}", data);
Err(ProgramError::InvalidInstructionData)
}
}
@ -190,7 +190,7 @@ mod test {
assert_eq!(tx.instructions.len(), 1);
let Instruction {
ref accounts,
ref userdata,
ref data,
..
} = tx.instructions[0];
@ -207,7 +207,7 @@ mod test {
.map(|((key, is_signer), account)| KeyedAccount::new(key, is_signer, account))
.collect();
let ret = entrypoint(&id(), &mut keyed_accounts, &userdata, 42);
let ret = entrypoint(&id(), &mut keyed_accounts, &data, 42);
info!("ret: {:?}", ret);
ret
}
@ -236,8 +236,8 @@ mod test {
);
assert_eq!(
entrypoint(&id(), &mut keyed_accounts, &tx.instructions[0].userdata, 42),
Err(ProgramError::UserdataTooSmall)
entrypoint(&id(), &mut keyed_accounts, &tx.instructions[0].data, 42),
Err(ProgramError::AccountDataTooSmall)
);
}
@ -265,7 +265,7 @@ mod test {
solana_logger::setup();
let keypair = Keypair::new();
let mut accounts = [Account::default(), Account::default()];
accounts[1].userdata.resize(16 * 1024, 0);
accounts[1].data.resize(16 * 1024, 0);
let tx = StorageTransaction::new_mining_proof(
&keypair,
@ -284,7 +284,7 @@ mod test {
solana_logger::setup();
let keypair = Keypair::new();
let mut accounts = [Account::default(), Account::default()];
accounts[0].userdata.resize(16 * 1024, 0);
accounts[0].data.resize(16 * 1024, 0);
let tx = StorageTransaction::new_advertise_recent_blockhash(
&keypair,
@ -311,7 +311,7 @@ mod test {
solana_logger::setup();
let keypair = Keypair::new();
let mut accounts = [Account::default(), Account::default()];
accounts[0].userdata.resize(16 * 1024, 0);
accounts[0].data.resize(16 * 1024, 0);
let entry_height = 0;

View File

@ -11,7 +11,7 @@ use solana_storage_api::{StorageTransaction, ENTRIES_PER_SEGMENT};
fn get_storage_entry_height(bank: &Bank, account: &Pubkey) -> u64 {
match bank.get_account(&account) {
Some(storage_system_account) => {
let state = deserialize(&storage_system_account.userdata);
let state = deserialize(&storage_system_account.data);
if let Ok(state) = state {
let state: solana_storage_api::StorageProgramState = state;
return state.entry_height;
@ -26,7 +26,7 @@ fn get_storage_entry_height(bank: &Bank, account: &Pubkey) -> u64 {
fn get_storage_blockhash(bank: &Bank, account: &Pubkey) -> Hash {
if let Some(storage_system_account) = bank.get_account(&account) {
let state = deserialize(&storage_system_account.userdata);
let state = deserialize(&storage_system_account.data);
if let Ok(state) = state {
let state: solana_storage_api::StorageProgramState = state;
return state.hash;

View File

@ -413,7 +413,7 @@ impl TokenProgram {
.map(|keyed_account| {
let account = &keyed_account.account;
if account.owner == *program_id {
match Self::deserialize(&account.userdata) {
match Self::deserialize(&account.data) {
Ok(token_program) => token_program,
Err(err) => {
error!("deserialize failed: {:?}", err);
@ -427,7 +427,7 @@ impl TokenProgram {
.collect();
for program_account in &input_program_accounts {
info!("input_program_account: userdata={:?}", program_account);
info!("input_program_account: data={:?}", program_account);
}
let mut output_program_accounts: Vec<(_, _)> = vec![];
@ -468,10 +468,10 @@ impl TokenProgram {
for (index, program_account) in &output_program_accounts {
info!(
"output_program_account: index={} userdata={:?}",
"output_program_account: index={} data={:?}",
index, program_account
);
Self::serialize(program_account, &mut info[*index].account.userdata)?;
Self::serialize(program_account, &mut info[*index].account.data)?;
}
Ok(())
}
@ -484,7 +484,7 @@ mod test {
pub fn serde() {
assert_eq!(TokenProgram::deserialize(&[0]), Ok(TokenProgram::default()));
let mut userdata = vec![0; 256];
let mut data = vec![0; 256];
let account = TokenProgram::Account(TokenAccountInfo {
token: Pubkey::new(&[1; 32]),
@ -492,8 +492,8 @@ mod test {
amount: 123,
delegate: None,
});
account.serialize(&mut userdata).unwrap();
assert_eq!(TokenProgram::deserialize(&userdata), Ok(account));
account.serialize(&mut data).unwrap();
assert_eq!(TokenProgram::deserialize(&data), Ok(account));
let account = TokenProgram::Token(TokenInfo {
supply: 12345,
@ -501,23 +501,23 @@ mod test {
name: "A test token".to_string(),
symbol: "TEST".to_string(),
});
account.serialize(&mut userdata).unwrap();
assert_eq!(TokenProgram::deserialize(&userdata), Ok(account));
account.serialize(&mut data).unwrap();
assert_eq!(TokenProgram::deserialize(&data), Ok(account));
}
#[test]
pub fn serde_expect_fail() {
let mut userdata = vec![0; 256];
let mut data = vec![0; 256];
// Certain TokenProgram's may not be serialized
let account = TokenProgram::default();
assert_eq!(account, TokenProgram::Unallocated);
assert!(account.serialize(&mut userdata).is_err());
assert!(account.serialize(&mut userdata).is_err());
assert!(account.serialize(&mut data).is_err());
assert!(account.serialize(&mut data).is_err());
let account = TokenProgram::Invalid;
assert!(account.serialize(&mut userdata).is_err());
assert!(account.serialize(&mut data).is_err());
// Bad deserialize userdata
// Bad deserialize data
assert!(TokenProgram::deserialize(&[]).is_err());
assert!(TokenProgram::deserialize(&[1]).is_err());
assert!(TokenProgram::deserialize(&[1, 2]).is_err());

View File

@ -22,7 +22,7 @@ fn entrypoint(
trace!("process_instruction: {:?}", data);
trace!("keyed_accounts: {:?}", keyed_accounts);
match deserialize(data).map_err(|_| ProgramError::InvalidUserdata)? {
match deserialize(data).map_err(|_| ProgramError::InvalidInstructionData)? {
VoteInstruction::InitializeAccount => vote_state::initialize_account(keyed_accounts),
VoteInstruction::DelegateStake(delegate_id) => {
vote_state::delegate_stake(keyed_accounts, &delegate_id)

View File

@ -64,7 +64,7 @@ impl<'a> VoteBank<'a> {
self.bank.register_tick(&hash(blockhash.as_ref()));
let vote_account = self.bank.get_account(&vote_keypair.pubkey()).unwrap();
Ok(VoteState::deserialize(&vote_account.userdata).unwrap())
Ok(VoteState::deserialize(&vote_account.data).unwrap())
}
}
@ -129,7 +129,7 @@ fn test_vote_via_bank_with_no_signature() {
// And ensure there's no vote.
let vote_account = bank.get_account(&vote_id).unwrap();
let vote_state = VoteState::deserialize(&vote_account.userdata).unwrap();
let vote_state = VoteState::deserialize(&vote_account.data).unwrap();
assert_eq!(vote_state.votes.len(), 0);
assert_eq!(

View File

@ -74,12 +74,12 @@ impl VoteState {
}
pub fn deserialize(input: &[u8]) -> Result<Self, ProgramError> {
deserialize(input).map_err(|_| ProgramError::InvalidUserdata)
deserialize(input).map_err(|_| ProgramError::InvalidAccountData)
}
pub fn serialize(&self, output: &mut [u8]) -> Result<(), ProgramError> {
serialize_into(output, self).map_err(|err| match *err {
ErrorKind::SizeLimit => ProgramError::UserdataTooSmall,
ErrorKind::SizeLimit => ProgramError::AccountDataTooSmall,
_ => ProgramError::GenericError,
})
}
@ -163,13 +163,13 @@ pub fn delegate_stake(
Err(ProgramError::InvalidArgument)?;
}
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata);
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.data);
if let Ok(mut vote_state) = vote_state {
vote_state.delegate_id = *node_id;
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
vote_state.serialize(&mut keyed_accounts[0].account.data)?;
} else {
error!("account[0] does not valid userdata");
Err(ProgramError::InvalidUserdata)?;
error!("account[0] does not valid data");
Err(ProgramError::InvalidAccountData)?;
}
Ok(())
@ -192,13 +192,13 @@ pub fn authorize_voter(
Err(ProgramError::InvalidArgument)?;
}
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata);
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.data);
if let Ok(mut vote_state) = vote_state {
vote_state.authorized_voter_id = *voter_id;
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
vote_state.serialize(&mut keyed_accounts[0].account.data)?;
} else {
error!("account[0] does not valid userdata");
Err(ProgramError::InvalidUserdata)?;
error!("account[0] does not valid data");
Err(ProgramError::InvalidAccountData)?;
}
Ok(())
@ -214,18 +214,18 @@ pub fn initialize_account(keyed_accounts: &mut [KeyedAccount]) -> Result<(), Pro
}
let staker_id = keyed_accounts[0].unsigned_key();
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata);
let vote_state = VoteState::deserialize(&keyed_accounts[0].account.data);
if let Ok(vote_state) = vote_state {
if vote_state.delegate_id == Pubkey::default() {
let vote_state = VoteState::new(staker_id);
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
vote_state.serialize(&mut keyed_accounts[0].account.data)?;
} else {
error!("account[0] userdata already initialized");
Err(ProgramError::InvalidUserdata)?;
error!("account[0] data already initialized");
Err(ProgramError::InvalidAccountData)?;
}
} else {
error!("account[0] does not have valid userdata");
Err(ProgramError::InvalidUserdata)?;
error!("account[0] does not have valid data");
Err(ProgramError::InvalidAccountData)?;
}
Ok(())
@ -237,7 +237,7 @@ pub fn process_vote(keyed_accounts: &mut [KeyedAccount], vote: Vote) -> Result<(
Err(ProgramError::InvalidArgument)?;
}
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?;
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.data)?;
// If no voter was authorized, expect account[0] to be the signer, otherwise account[1].
let signer_index = if vote_state.authorized_voter_id == *keyed_accounts[0].unsigned_key() {
@ -256,7 +256,7 @@ pub fn process_vote(keyed_accounts: &mut [KeyedAccount], vote: Vote) -> Result<(
}
vote_state.process_vote(vote);
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
vote_state.serialize(&mut keyed_accounts[0].account.data)?;
Ok(())
}
@ -266,9 +266,9 @@ pub fn clear_credits(keyed_accounts: &mut [KeyedAccount]) -> Result<(), ProgramE
Err(ProgramError::InvalidArgument)?;
}
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?;
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.data)?;
vote_state.clear_credits();
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
vote_state.serialize(&mut keyed_accounts[0].account.data)?;
Ok(())
}
@ -283,7 +283,7 @@ pub fn initialize_and_deserialize(
) -> Result<VoteState, ProgramError> {
let mut keyed_accounts = [KeyedAccount::new(vote_id, false, vote_account)];
initialize_account(&mut keyed_accounts)?;
let vote_state = VoteState::deserialize(&vote_account.userdata).unwrap();
let vote_state = VoteState::deserialize(&vote_account.data).unwrap();
Ok(vote_state)
}
@ -294,7 +294,7 @@ pub fn vote_and_deserialize(
) -> Result<VoteState, ProgramError> {
let mut keyed_accounts = [KeyedAccount::new(vote_id, true, vote_account)];
process_vote(&mut keyed_accounts, vote)?;
let vote_state = VoteState::deserialize(&vote_account.userdata).unwrap();
let vote_state = VoteState::deserialize(&vote_account.data).unwrap();
Ok(vote_state)
}
@ -324,7 +324,7 @@ mod tests {
// reinit should fail
let res = initialize_account(&mut keyed_accounts);
assert_eq!(res, Err(ProgramError::InvalidUserdata));
assert_eq!(res, Err(ProgramError::InvalidAccountData));
}
#[test]

View File

@ -108,7 +108,7 @@ impl VoteTransaction {
if !check_id(&tx.program_id(ix_index)) {
return None;
}
let instruction = deserialize(&tx.userdata(ix_index)).unwrap();
let instruction = deserialize(&tx.data(ix_index)).unwrap();
if let VoteInstruction::Vote(vote) = instruction {
Some((tx.account_keys[0], vote, tx.recent_blockhash))
} else {

View File

@ -451,7 +451,7 @@ impl AccountsDB {
// when squashing.
let acc = &mut account.clone();
if account.lamports == 0 {
acc.userdata.resize(0, 0);
acc.data.resize(0, 0);
}
loop {
@ -1617,7 +1617,7 @@ mod tests {
}
fn compare_account(account1: &Account, account2: &Account) -> bool {
if account1.userdata != account2.userdata
if account1.data != account2.data
|| account1.owner != account2.owner
|| account1.executable != account2.executable
|| account1.lamports != account2.lamports

View File

@ -33,7 +33,7 @@ fn get_account_size_static() -> usize {
}
pub fn get_serialized_size(account: &Account) -> usize {
get_account_size_static() + account.userdata.len()
get_account_size_static() + account.data.len()
}
pub fn serialize_account(dst_slice: &mut [u8], account: &Account, len: usize) {
@ -41,7 +41,7 @@ pub fn serialize_account(dst_slice: &mut [u8], account: &Account, len: usize) {
write_u64(&mut at, dst_slice, len as u64);
write_u64(&mut at, dst_slice, account.lamports);
write_bytes(&mut at, dst_slice, &account.userdata);
write_bytes(&mut at, dst_slice, &account.data);
write_bytes(&mut at, dst_slice, account.owner.as_ref());
write_bytes(&mut at, dst_slice, &[account.executable as u8]);
}
@ -83,9 +83,9 @@ pub fn deserialize_account(
let lamports = read_u64(&mut at, &src_slice);
let userdata_len = len - get_account_size_static();
let mut userdata = vec![0; userdata_len];
read_bytes(&mut at, &mut userdata, &src_slice, userdata_len);
let data_len = len - get_account_size_static();
let mut data = vec![0; data_len];
read_bytes(&mut at, &mut data, &src_slice, data_len);
let mut pubkey = vec![0; mem::size_of::<Pubkey>()];
read_bytes(&mut at, &mut pubkey, &src_slice, mem::size_of::<Pubkey>());
@ -97,7 +97,7 @@ pub fn deserialize_account(
Ok(Account {
lamports,
userdata,
data,
owner,
executable,
})
@ -256,7 +256,7 @@ pub mod tests {
let v1 = vec![1u8; 32];
let mut account1 = Account {
lamports: 1,
userdata: v1,
data: v1,
owner: Pubkey::default(),
executable: false,
};
@ -267,7 +267,7 @@ pub mod tests {
let v2 = vec![4u8; 32];
let mut account2 = Account {
lamports: 1,
userdata: v2,
data: v2,
owner: Pubkey::default(),
executable: false,
};
@ -277,13 +277,13 @@ pub mod tests {
assert_eq!(av.get_account(index2).unwrap(), account2);
assert_eq!(av.get_account(index1).unwrap(), account1);
account2.userdata.iter_mut().for_each(|e| *e *= 2);
account2.data.iter_mut().for_each(|e| *e *= 2);
let index3 = av.append_account(&account2).unwrap();
len += get_serialized_size(&account2) + SIZEOF_U64 as usize;
assert_eq!(index3, len as u64);
assert_eq!(av.get_account(index3).unwrap(), account2);
account1.userdata.extend([1, 2, 3, 4, 5, 6].iter().cloned());
account1.data.extend([1, 2, 3, 4, 5, 6].iter().cloned());
let index4 = av.append_account(&account1).unwrap();
len += get_serialized_size(&account2) + SIZEOF_U64 as usize;
assert_eq!(index4, len as u64);

View File

@ -293,7 +293,7 @@ impl Bank {
// will be forced to select it as the leader for height 0
let mut bootstrap_leader_vote_account = Account {
lamports: bootstrap_leader_stake,
userdata: vec![0; VoteState::max_size() as usize],
data: vec![0; VoteState::max_size() as usize],
owner: solana_vote_api::id(),
executable: false,
};
@ -301,7 +301,7 @@ impl Bank {
let mut vote_state = VoteState::new(&genesis_block.bootstrap_leader_id);
vote_state.votes.push_back(Lockout::new(&Vote::new(0)));
vote_state
.serialize(&mut bootstrap_leader_vote_account.userdata)
.serialize(&mut bootstrap_leader_vote_account.data)
.unwrap();
self.accounts.store_slow(
@ -929,12 +929,12 @@ mod tests {
let instructions = vec![
Instruction {
program_ids_index: 0,
userdata: serialize(&spend).unwrap(),
data: serialize(&spend).unwrap(),
accounts: vec![0, 1],
},
Instruction {
program_ids_index: 0,
userdata: serialize(&spend).unwrap(),
data: serialize(&spend).unwrap(),
accounts: vec![0, 2],
},
];
@ -1427,7 +1427,7 @@ mod tests {
accounts
.iter()
.filter_map(|(pubkey, account)| {
if let Ok(vote_state) = VoteState::deserialize(&account.userdata) {
if let Ok(vote_state) = VoteState::deserialize(&account.data) {
if vote_state.delegate_id == leader_id {
Some((*pubkey, true))
} else {

View File

@ -49,13 +49,13 @@ fn create_path(name: &str) -> PathBuf {
pub fn entrypoint(
program_id: &Pubkey,
keyed_accounts: &mut [KeyedAccount],
ix_userdata: &[u8],
ix_data: &[u8],
tick_height: u64,
) -> Result<(), ProgramError> {
if keyed_accounts[0].account.executable {
// dispatch it
let (names, params) = keyed_accounts.split_at_mut(1);
let name = &names[0].account.userdata;
let name = &names[0].account.data;
let name = match str::from_utf8(name) {
Ok(v) => v,
Err(e) => {
@ -80,14 +80,14 @@ pub fn entrypoint(
return Err(ProgramError::GenericError);
}
};
return entrypoint(program_id, params, ix_userdata, tick_height);
return entrypoint(program_id, params, ix_data, tick_height);
},
Err(e) => {
warn!("Unable to load: {:?}", e);
return Err(ProgramError::GenericError);
}
}
} else if let Ok(instruction) = deserialize(ix_userdata) {
} else if let Ok(instruction) = deserialize(ix_data) {
if keyed_accounts[0].signer_key().is_none() {
warn!("key[0] did not sign the transaction");
return Err(ProgramError::GenericError);
@ -96,16 +96,16 @@ pub fn entrypoint(
LoaderInstruction::Write { offset, bytes } => {
trace!("NativeLoader::Write offset {} bytes {:?}", offset, bytes);
let offset = offset as usize;
if keyed_accounts[0].account.userdata.len() < offset + bytes.len() {
if keyed_accounts[0].account.data.len() < offset + bytes.len() {
warn!(
"Error: Overflow, {} < {}",
keyed_accounts[0].account.userdata.len(),
keyed_accounts[0].account.data.len(),
offset + bytes.len()
);
return Err(ProgramError::GenericError);
}
// native loader takes a name and we assume it all comes in at once
keyed_accounts[0].account.userdata = bytes;
keyed_accounts[0].account.data = bytes;
}
LoaderInstruction::Finalize => {
@ -117,7 +117,7 @@ pub fn entrypoint(
}
}
} else {
warn!("Invalid userdata in instruction: {:?}", ix_userdata);
warn!("Invalid data in instruction: {:?}", ix_data);
return Err(ProgramError::GenericError);
}
Ok(())

View File

@ -34,14 +34,14 @@ fn process_instruction(
crate::system_program::entrypoint(
&program_id,
&mut keyed_accounts[1..],
&tx.instructions[instruction_index].userdata,
&tx.instructions[instruction_index].data,
tick_height,
)
} else {
native_loader::entrypoint(
&program_id,
&mut keyed_accounts,
&tx.instructions[instruction_index].userdata,
&tx.instructions[instruction_index].data,
tick_height,
)
}
@ -51,7 +51,7 @@ fn verify_instruction(
program_id: &Pubkey,
pre_program_id: &Pubkey,
pre_lamports: u64,
pre_userdata: &[u8],
pre_data: &[u8],
account: &Account,
) -> Result<(), InstructionError> {
// Verify the transaction
@ -64,12 +64,12 @@ fn verify_instruction(
if *program_id != account.owner && pre_lamports > account.lamports {
return Err(InstructionError::ExternalAccountLamportSpend);
}
// For accounts unassigned to the program, the userdata may not change.
// For accounts unassigned to the program, the data may not change.
if *program_id != account.owner
&& !system_program::check_id(&program_id)
&& pre_userdata != &account.userdata[..]
&& pre_data != &account.data[..]
{
return Err(InstructionError::ExternalAccountUserdataModified);
return Err(InstructionError::ExternalAccountDataModified);
}
Ok(())
}
@ -91,7 +91,7 @@ fn execute_instruction(
let pre_total: u64 = program_accounts.iter().map(|a| a.lamports).sum();
let pre_data: Vec<_> = program_accounts
.iter_mut()
.map(|a| (a.owner, a.lamports, a.userdata.clone()))
.map(|a| (a.owner, a.lamports, a.data.clone()))
.collect();
process_instruction(
@ -105,14 +105,14 @@ fn execute_instruction(
.map_err(InstructionError::ProgramError)?;
// Verify the instruction
for ((pre_program_id, pre_lamports, pre_userdata), post_account) in
for ((pre_program_id, pre_lamports, pre_data), post_account) in
pre_data.iter().zip(program_accounts.iter())
{
verify_instruction(
&program_id,
pre_program_id,
*pre_lamports,
pre_userdata,
pre_data,
post_account,
)?;
}
@ -212,10 +212,10 @@ where
let program_id = tx.program_id(i);
if system_program::check_id(&program_id) {
crate::system_program::entrypoint(&program_id, &mut keyed_accounts, &ix.userdata, 0)
crate::system_program::entrypoint(&program_id, &mut keyed_accounts, &ix.data, 0)
.unwrap();
} else {
process_instruction(&program_id, &mut keyed_accounts, &ix.userdata)?;
process_instruction(&program_id, &mut keyed_accounts, &ix.data)?;
}
}
Ok(())
@ -292,8 +292,8 @@ mod tests {
}
#[test]
fn test_verify_instruction_change_userdata() {
fn change_userdata(program_id: &Pubkey) -> Result<(), InstructionError> {
fn test_verify_instruction_change_data() {
fn change_data(program_id: &Pubkey) -> Result<(), InstructionError> {
let alice_program_id = Keypair::new().pubkey();
let account = Account::new(0, 0, &alice_program_id);
verify_instruction(&program_id, &alice_program_id, 0, &[42], &account)
@ -303,14 +303,14 @@ mod tests {
let mallory_program_id = Keypair::new().pubkey();
assert_eq!(
change_userdata(&system_program_id),
change_data(&system_program_id),
Ok(()),
"system program should be able to change the userdata"
"system program should be able to change the data"
);
assert_eq!(
change_userdata(&mallory_program_id),
Err(InstructionError::ExternalAccountUserdataModified),
"malicious Mallory should not be able to change the account userdata"
change_data(&mallory_program_id),
Err(InstructionError::ExternalAccountDataModified),
"malicious Mallory should not be able to change the account data"
);
}

View File

@ -20,7 +20,7 @@ fn create_system_account(
Err(SystemError::SourceNotSystemAccount)?;
}
if !keyed_accounts[TO_ACCOUNT_INDEX].account.userdata.is_empty()
if !keyed_accounts[TO_ACCOUNT_INDEX].account.data.is_empty()
|| !system_program::check_id(&keyed_accounts[TO_ACCOUNT_INDEX].account.owner)
{
info!(
@ -39,7 +39,7 @@ fn create_system_account(
keyed_accounts[FROM_ACCOUNT_INDEX].account.lamports -= lamports;
keyed_accounts[TO_ACCOUNT_INDEX].account.lamports += lamports;
keyed_accounts[TO_ACCOUNT_INDEX].account.owner = *program_id;
keyed_accounts[TO_ACCOUNT_INDEX].account.userdata = vec![0; space as usize];
keyed_accounts[TO_ACCOUNT_INDEX].account.data = vec![0; space as usize];
keyed_accounts[TO_ACCOUNT_INDEX].account.executable = false;
Ok(())
}
@ -96,8 +96,8 @@ pub fn entrypoint(
}
.map_err(|e| ProgramError::CustomError(serialize(&e).unwrap()))
} else {
info!("Invalid transaction instruction userdata: {:?}", data);
Err(ProgramError::InvalidUserdata)
info!("Invalid instruction data: {:?}", data);
Err(ProgramError::InvalidInstructionData)
}
}
@ -124,11 +124,11 @@ mod tests {
let from_lamports = from_account.lamports;
let to_lamports = to_account.lamports;
let to_owner = to_account.owner;
let to_userdata = to_account.userdata.clone();
let to_data = to_account.data.clone();
assert_eq!(from_lamports, 50);
assert_eq!(to_lamports, 50);
assert_eq!(to_owner, new_program_owner);
assert_eq!(to_userdata, [0, 0]);
assert_eq!(to_data, [0, 0]);
}
#[test]
@ -177,8 +177,8 @@ mod tests {
}
#[test]
fn test_create_userdata_populated() {
// Attempt to create system account in account with populated userdata
fn test_create_data_populated() {
// Attempt to create system account in account with populated data
let new_program_owner = Pubkey::new(&[9; 32]);
let from = Keypair::new().pubkey();
let mut from_account = Account::new(100, 0, &system_program::id());
@ -186,7 +186,7 @@ mod tests {
let populated_key = Keypair::new().pubkey();
let mut populated_account = Account {
lamports: 0,
userdata: vec![0, 1, 2, 3],
data: vec![0, 1, 2, 3],
owner: Pubkey::default(),
executable: false,
};

View File

@ -1,39 +1,36 @@
use crate::pubkey::Pubkey;
use std::{cmp, fmt};
/// An Account with userdata that is stored on chain
/// An Account with data that is stored on chain
#[repr(C)]
#[derive(Serialize, Deserialize, Clone, Default, Eq, PartialEq)]
pub struct Account {
/// lamports in the account
pub lamports: u64,
/// data held in this account
pub userdata: Vec<u8>,
pub data: Vec<u8>,
/// the program that owns this account. If executable, the program that loads this account.
pub owner: Pubkey,
/// this account's userdata contains a loaded program (and is now read-only)
/// this account's data contains a loaded program (and is now read-only)
pub executable: bool,
}
impl fmt::Debug for Account {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let userdata_len = cmp::min(64, self.userdata.len());
let userdata_str = if userdata_len > 0 {
format!(
" userdata: {}",
hex::encode(self.userdata[..userdata_len].to_vec())
)
let data_len = cmp::min(64, self.data.len());
let data_str = if data_len > 0 {
format!(" data: {}", hex::encode(self.data[..data_len].to_vec()))
} else {
"".to_string()
};
write!(
f,
"Account {{ lamports: {} userdata.len: {} owner: {} executable: {}{} }}",
"Account {{ lamports: {} data.len: {} owner: {} executable: {}{} }}",
self.lamports,
self.userdata.len(),
self.data.len(),
self.owner,
self.executable,
userdata_str,
data_str,
)
}
}
@ -43,7 +40,7 @@ impl Account {
pub fn new(lamports: u64, space: usize, owner: &Pubkey) -> Account {
Account {
lamports,
userdata: vec![0u8; space],
data: vec![0u8; space],
owner: *owner,
executable: false,
}

View File

@ -18,7 +18,7 @@ pub fn create_program_account(name: &str) -> Account {
Account {
lamports: 1,
owner: id(),
userdata: name.as_bytes().to_vec(),
data: name.as_bytes().to_vec(),
executable: true,
}
}

View File

@ -11,11 +11,14 @@ pub enum ProgramError {
/// The arguments provided to a program instruction where invalid
InvalidArgument,
/// An account's userdata contents was invalid
InvalidUserdata,
/// An instruction's data contents was invalid
InvalidInstructionData,
/// An account's userdata was too small
UserdataTooSmall,
/// An account's data contents was invalid
InvalidAccountData,
/// An account's data was too small
AccountDataTooSmall,
/// The account did not have the expected program id
IncorrectProgramId,

View File

@ -32,8 +32,8 @@ pub enum InstructionError {
/// Program spent the lamports of an account that doesn't belong to it
ExternalAccountLamportSpend,
/// Program modified the userdata of an account that doesn't belong to it
ExternalAccountUserdataModified,
/// Program modified the data of an account that doesn't belong to it
ExternalAccountDataModified,
}
impl InstructionError {
@ -52,15 +52,15 @@ pub struct Instruction<P, Q> {
/// Ordered indices into the transaction keys array indicating which accounts to pass to the program
pub accounts: Vec<Q>,
/// The program input data
pub userdata: Vec<u8>,
pub data: Vec<u8>,
}
impl<P, Q> Instruction<P, Q> {
pub fn new<T: Serialize>(program_ids_index: P, userdata: &T, accounts: Vec<Q>) -> Self {
let userdata = serialize(userdata).unwrap();
pub fn new<T: Serialize>(program_ids_index: P, data: &T, accounts: Vec<Q>) -> Self {
let data = serialize(data).unwrap();
Self {
program_ids_index,
userdata,
data,
accounts,
}
}
@ -70,7 +70,7 @@ impl Instruction<u8, u8> {
pub fn serialize_with(mut writer: &mut Cursor<&mut [u8]>, ix: &Self) -> Result<(), Error> {
writer.write_all(&[ix.program_ids_index])?;
serialize_vec_bytes(&mut writer, &ix.accounts[..])?;
serialize_vec_bytes(&mut writer, &ix.userdata[..])?;
serialize_vec_bytes(&mut writer, &ix.data[..])?;
Ok(())
}
@ -79,11 +79,11 @@ impl Instruction<u8, u8> {
reader.read_exact(&mut buf)?;
let program_ids_index = buf[0];
let accounts = deserialize_vec_bytes(&mut reader)?;
let userdata = deserialize_vec_bytes(&mut reader)?;
let data = deserialize_vec_bytes(&mut reader)?;
Ok(Instruction {
program_ids_index,
accounts,
userdata,
data,
})
}
@ -96,7 +96,7 @@ impl Instruction<u8, u8> {
encode_len(&mut wr, len)?;
size += wr.position() as usize + (len * size_of::<u8>());
let len = self.userdata.len();
let len = self.data.len();
wr.set_position(0);
encode_len(&mut wr, len)?;
size += wr.position() as usize + (len * size_of::<u8>());
@ -164,13 +164,13 @@ impl Transaction {
from_keypair: &T,
transaction_keys: &[Pubkey],
program_id: &Pubkey,
userdata: &S,
data: &S,
recent_blockhash: Hash,
fee: u64,
) -> Self {
let program_ids = vec![*program_id];
let accounts = (0..=transaction_keys.len() as u8).collect();
let instructions = vec![Instruction::new(0, userdata, accounts)];
let instructions = vec![Instruction::new(0, data, accounts)];
Self::new_with_instructions(
&[from_keypair],
transaction_keys,
@ -184,13 +184,13 @@ impl Transaction {
from_pubkey: &Pubkey,
transaction_keys: &[Pubkey],
program_id: &Pubkey,
userdata: &T,
data: &T,
recent_blockhash: Hash,
fee: u64,
) -> Self {
let program_ids = vec![*program_id];
let accounts = (0..=transaction_keys.len() as u8).collect();
let instructions = vec![Instruction::new(0, userdata, accounts)];
let instructions = vec![Instruction::new(0, data, accounts)];
let mut keys = vec![*from_pubkey];
keys.extend_from_slice(transaction_keys);
Self::new_with_instructions::<Keypair>(
@ -234,8 +234,8 @@ impl Transaction {
tx.sign(from_keypairs, recent_blockhash);
tx
}
pub fn userdata(&self, instruction_index: usize) -> &[u8] {
&self.instructions[instruction_index].userdata
pub fn data(&self, instruction_index: usize) -> &[u8] {
&self.instructions[instruction_index].data
}
fn key_index(&self, instruction_index: usize, accounts_index: usize) -> Option<usize> {
@ -595,7 +595,7 @@ mod tests {
assert_eq!(req_size, size);
}
/// Detect binary changes in the serialized transaction userdata, which could have a downstream
/// Detect binary changes in the serialized transaction data, which could have a downstream
/// affect on SDKs and DApps
#[test]
fn test_sdk_serialize() {

View File

@ -20,7 +20,7 @@ fn compile_instruction(
let accounts: Vec<_> = ix.accounts.iter().map(|(k, _)| position(keys, k)).collect();
Instruction {
program_ids_index: position(program_ids, &ix.program_ids_index),
userdata: ix.userdata.clone(),
data: ix.data.clone(),
accounts,
}
}

View File

@ -65,11 +65,11 @@ fn test_bad_sig() {
let blockhash = client.get_recent_blockhash();
let mut tr2 = SystemTransaction::new_account(&alice, &bob_pubkey, 501, blockhash, 0);
let mut instruction2 = deserialize(tr2.userdata(0)).unwrap();
let mut instruction2 = deserialize(tr2.data(0)).unwrap();
if let SystemInstruction::Move { ref mut lamports } = instruction2 {
*lamports = 502;
}
tr2.instructions[0].userdata = serialize(&instruction2).unwrap();
tr2.instructions[0].data = serialize(&instruction2).unwrap();
let signature = client.transfer_signed(&tr2).unwrap();
client.poll_for_signature(&signature).unwrap();
@ -113,9 +113,9 @@ fn test_register_vote_account() {
const LAST: usize = 30;
for run in 0..=LAST {
let account_user_data = client
.get_account_userdata(&vote_account_id)
.expect("Expected valid response for account userdata")
.expect("Expected valid account userdata to exist after account creation");
.get_account_data(&vote_account_id)
.expect("Expected valid response for account data")
.expect("Expected valid account data to exist after account creation");
let vote_state = VoteState::deserialize(&account_user_data);

View File

@ -494,8 +494,8 @@ fn process_deploy(
format!("Unable to open program file: {}", err).to_string(),
)
})?;
let mut program_userdata = Vec::new();
file.read_to_end(&mut program_userdata).map_err(|err| {
let mut program_data = Vec::new();
file.read_to_end(&mut program_data).map_err(|err| {
WalletError::DynamicProgramError(
format!("Unable to read program file: {}", err).to_string(),
)
@ -506,7 +506,7 @@ fn process_deploy(
&program_id.pubkey(),
blockhash,
1,
program_userdata.len() as u64,
program_data.len() as u64,
&bpf_loader::id(),
0,
);
@ -516,7 +516,7 @@ fn process_deploy(
})?;
trace!("Writing program data");
let write_transactions: Vec<_> = program_userdata
let write_transactions: Vec<_> = program_data
.chunks(USERDATA_CHUNK_SIZE)
.zip(0..)
.map(|(chunk, i)| {

View File

@ -70,11 +70,7 @@ fn test_wallet_deploy_program() {
file.read_to_end(&mut elf).unwrap();
assert_eq!(
account_info_obj
.get("userdata")
.unwrap()
.as_array()
.unwrap(),
account_info_obj.get("data").unwrap().as_array().unwrap(),
&elf
);