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:
parent
de13082347
commit
c1eec0290e
|
@ -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}}
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
})
|
||||
|
|
|
@ -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,
|
||||
..
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)| {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue