Skip to content

Commit

Permalink
Merge pull request #1100 from aludvik/stl-819.no-block-id
Browse files Browse the repository at this point in the history
STL 819 - ClientBlockGetBy{Transaction,Batch}Request
  • Loading branch information
Adam M Ludvik authored Nov 13, 2017
2 parents 87d22c7 + f242c27 commit 6dddb20
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 19 deletions.
27 changes: 22 additions & 5 deletions families/seth/rpc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use sawtooth_sdk::messages::client_block::{
ClientBlockListResponse,
ClientBlockGetByIdRequest,
ClientBlockGetByNumRequest,
ClientBlockGetByTransactionIdRequest,
ClientBlockGetResponse,
ClientBlockGetResponse_Status,
};
Expand Down Expand Up @@ -75,6 +76,7 @@ pub enum BlockKey {
Earliest,
Number(u64),
Signature(String),
Transaction(String),
}

pub enum BlockKeyParseError {
Expand Down Expand Up @@ -391,11 +393,7 @@ impl<S: MessageSender> ValidatorClient<S> {
Message_MessageType::CLIENT_TRANSACTION_GET_REQUEST, &request)?;

let block = {
if response.block_id == "" {
None
} else {
self.get_block(BlockKey::Signature(response.block_id.clone())).ok()
}
self.get_block(BlockKey::Transaction(txn_id.clone())).ok()
};

match response.status {
Expand Down Expand Up @@ -455,6 +453,12 @@ impl<S: MessageSender> ValidatorClient<S> {
request.set_block_id(String::from("0000000000000000"));
response = self.send_request(message_type, &request)?;
},
BlockKey::Transaction(transaction_id) => {
let mut request = ClientBlockGetByTransactionIdRequest::new();
let message_type: Message_MessageType = Message_MessageType::CLIENT_BLOCK_GET_BY_TRANSACTION_ID_REQUEST;
request.set_transaction_id(transaction_id);
response = self.send_request(message_type, &request)?;
},
};

match response.status {
Expand Down Expand Up @@ -497,6 +501,14 @@ impl<S: MessageSender> ValidatorClient<S> {
return Err(String::from(format!("{:?}", error)));
},
},
BlockKey::Transaction(transaction_id) => match self.transaction_to_block_id(transaction_id) {
Ok(block_id) => {
request.set_head_id(block_id);
},
Err(error) => {
return Err(String::from(format!("{:?}", error)));
},
},
}

let response: ClientStateGetResponse =
Expand Down Expand Up @@ -612,4 +624,9 @@ impl<S: MessageSender> ValidatorClient<S> {
self.get_block(BlockKey::Number(block_num)).map(|block|
String::from(block.header_signature))
}

fn transaction_to_block_id(&mut self, transaction_id: String) -> Result<String, Error> {
self.get_block(BlockKey::Transaction(transaction_id)).map(|block|
String::from(block.header_signature))
}
}
16 changes: 12 additions & 4 deletions families/seth/rpc/tests/test_seth_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from sawtooth_sdk.protobuf.client_block_pb2 import ClientBlockListResponse
from sawtooth_sdk.protobuf.client_block_pb2 import ClientBlockGetByIdRequest
from sawtooth_sdk.protobuf.client_block_pb2 import ClientBlockGetByNumRequest
from sawtooth_sdk.protobuf.client_block_pb2 import \
ClientBlockGetByTransactionIdRequest
from sawtooth_sdk.protobuf.client_block_pb2 import ClientBlockGetResponse
from sawtooth_sdk.protobuf.client_state_pb2 import ClientStateGetRequest
from sawtooth_sdk.protobuf.client_state_pb2 import ClientStateGetResponse
Expand Down Expand Up @@ -498,7 +500,7 @@ def test_get_transaction_by_hash(self):

self._send_transaction_response(msg, block.batches[1].transactions[1])

msg, request = self._receive_block_request_id()
msg, request = self._receive_block_request_transaction()

self._send_block_back(msg, block)

Expand Down Expand Up @@ -735,7 +737,7 @@ def test_get_transaction_receipt(self):

msg, request = self._receive_transaction_request()
self._send_transaction_response(msg)
msg, request = self._receive_block_request_id()
msg, request = self._receive_block_request_transaction()
block = Block(
header=BlockHeader(block_num=self.block_num).SerializeToString(),
header_signature=self.block_id,
Expand Down Expand Up @@ -1228,8 +1230,7 @@ def _send_transaction_response(self, msg, transaction=None):
Message.CLIENT_TRANSACTION_GET_RESPONSE,
ClientTransactionGetResponse(
status=ClientBlockGetResponse.OK,
transaction=transaction,
block_id=self.block_id),
transaction=transaction),
msg)


Expand All @@ -1247,6 +1248,13 @@ def _receive_receipt_request(self):
request.ParseFromString(msg.content)
return msg, request

def _receive_block_request_transaction(self):
msg = self.validator.receive()
self.assertEqual(msg.message_type,
Message.CLIENT_BLOCK_GET_BY_TRANSACTION_ID_REQUEST)
request = ClientBlockGetByTransactionIdRequest()
request.ParseFromString(msg.content)
return msg, request

def _receive_block_request_id(self):
msg = self.validator.receive()
Expand Down
14 changes: 14 additions & 0 deletions protos/client_block.proto
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,20 @@ message ClientBlockGetByNumRequest {
uint64 block_num = 1;
}

// A request to return a specific block from the validator. The block
// containing the given transaction is returned. If no block on the current
// chain contains the transaction, NO_RESOURCE is returned.
message ClientBlockGetByTransactionIdRequest {
string transaction_id = 1;
}

// A request to return a specific block from the validator. The block
// containing the given batch is returned. If no block on the current chain
// contains the batch, NO_RESOURCE is returned.
message ClientBlockGetByBatchIdRequest {
string batch_id = 1;
}

// A response that returns the block specified by a ClientBlockGetByIdRequest
// or ClientBlockGetByNumRequest.
//
Expand Down
4 changes: 0 additions & 4 deletions protos/client_transaction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,4 @@ message ClientTransactionGetResponse {
}
Status status = 1;
Transaction transaction = 2;

// Identifier of the block this transaction is in. Not set if the
// transaction is pending.
string block_id = 3;
}
2 changes: 2 additions & 0 deletions protos/validator.proto
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ message Message {
CLIENT_PEERS_GET_REQUEST = 125;
// A response with the validator's peers
CLIENT_PEERS_GET_RESPONSE = 126;
CLIENT_BLOCK_GET_BY_TRANSACTION_ID_REQUEST = 127;
CLIENT_BLOCK_GET_BY_BATCH_ID_REQUEST = 128;

// Message types for events
CLIENT_EVENTS_SUBSCRIBE_REQUEST = 500;
Expand Down
45 changes: 39 additions & 6 deletions validator/sawtooth_validator/state/client_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,44 @@ def _respond(self, request):
return self._wrap_response(block=block)


class BlockGetByTransactionRequest(_ClientRequestHandler):
def __init__(self, block_store):
super().__init__(
client_block_pb2.ClientBlockGetByTransactionIdRequest,
client_block_pb2.ClientBlockGetResponse,
validator_pb2.Message.CLIENT_BLOCK_GET_RESPONSE,
block_store=block_store)

def _respond(self, request):
try:
block = self._block_store.get_block_by_transaction_id(
request.transaction_id).block
except ValueError as e:
LOGGER.debug(e)
return self._status.NO_RESOURCE

return self._wrap_response(block=block)


class BlockGetByBatchRequest(_ClientRequestHandler):
def __init__(self, block_store):
super().__init__(
client_block_pb2.ClientBlockGetByBatchIdRequest,
client_block_pb2.ClientBlockGetResponse,
validator_pb2.Message.CLIENT_BLOCK_GET_RESPONSE,
block_store=block_store)

def _respond(self, request):
try:
block = self._block_store.get_block_by_batch_id(
request.batch_id).block
except ValueError as e:
LOGGER.debug(e)
return self._status.NO_RESOURCE

return self._wrap_response(block=block)


class BatchListRequest(_ClientRequestHandler):
def __init__(self, block_store):
super().__init__(
Expand Down Expand Up @@ -928,13 +966,8 @@ def _respond(self, request):
except ValueError as e:
LOGGER.debug(e)
return self._status.NO_RESOURCE
try:
block_id = self._block_store.get_block_by_transaction_id(
request.transaction_id).identifier
except ValueError as e:
block_id = ""

return self._wrap_response(transaction=txn, block_id=block_id)
return self._wrap_response(transaction=txn)


class PeersGetRequest(_ClientRequestHandler):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,97 @@ def test_block_get_with_batch_id(self):

self.assertEqual(self.status.NO_RESOURCE, response.status)
self.assertFalse(response.block.SerializeToString())


class TestBlockGetByTransactionRequests(ClientHandlerTestCase):
def setUp(self):
store = MockBlockStore()
self.initialize(
handlers.BlockGetByTransactionRequest(store),
client_block_pb2.ClientBlockGetByTransactionIdRequest,
client_block_pb2.ClientBlockGetResponse)

def test_block_get_request(self):
"""Verifies requests for a specific block by transaction work properly.
Expects to find:
- a status of OK
- the block property which is an instances of Block
- The block has a header_signature of 'B-1'
"""
response = self.make_request(transaction_id='t-1')

self.assertEqual(self.status.OK, response.status)
self.assertIsInstance(response.block, Block)
self.assertEqual('B-1', response.block.header_signature)

def test_block_get_bad_request(self):
"""Verifies requests for a specific block break with a bad protobuf.
Expects to find:
- a status of INTERNAL_ERROR
- that the Block returned, when serialized, is empty
"""
response = self.make_bad_request(transaction_id='t-1')

self.assertEqual(self.status.INTERNAL_ERROR, response.status)
self.assertFalse(response.block.SerializeToString())

def test_block_get_with_bad_id(self):
"""Verifies requests for a specific block break with a bad id.
Expects to find:
- a status of NO_RESOURCE
- that the Block returned, when serialized, is empty
"""
response = self.make_request(transaction_id='bad')

self.assertEqual(self.status.NO_RESOURCE, response.status)
self.assertFalse(response.block.SerializeToString())


class TestBlockGetByBatchRequests(ClientHandlerTestCase):
def setUp(self):
store = MockBlockStore()
self.initialize(
handlers.BlockGetByBatchRequest(store),
client_block_pb2.ClientBlockGetByBatchIdRequest,
client_block_pb2.ClientBlockGetResponse)

def test_block_get_request(self):
"""Verifies requests for a specific block by batch work properly.
Expects to find:
- a status of OK
- the block property which is an instances of Block
- The block has a header_signature of 'B-1'
"""
response = self.make_request(batch_id='b-1')

self.assertEqual(self.status.OK, response.status)
self.assertIsInstance(response.block, Block)
self.assertEqual('B-1', response.block.header_signature)

def test_block_get_bad_request(self):
"""Verifies requests for a specific block break with a bad protobuf.
Expects to find:
- a status of INTERNAL_ERROR
- that the Block returned, when serialized, is empty
"""
response = self.make_bad_request(batch_id='b-1')

self.assertEqual(self.status.INTERNAL_ERROR, response.status)
self.assertFalse(response.block.SerializeToString())

def test_block_get_with_bad_id(self):
"""Verifies requests for a specific block break with a bad id.
Expects to find:
- a status of NO_RESOURCE
- that the Block returned, when serialized, is empty
"""
response = self.make_request(batch_id='bad')

self.assertEqual(self.status.NO_RESOURCE, response.status)
self.assertFalse(response.block.SerializeToString())

0 comments on commit 6dddb20

Please sign in to comment.