나노 네트워크에서 송신 블록의 수명 주기 자세히 살펴보기
Nano 네트워크에서 송신 블록이 어떻게 기억됩니까?
A bystander look at the C++ reference implementation
나는 Nano 전류 참조 구현을 살펴보는 데 시간을 보냈습니다. 코드베이스가 방대해서 쉬운 작업은 아니었습니다. 저는 정확한 질문에 집중하고 싶었습니다. 송신 블록의 수명 주기는 무엇입니까? 이것은 내 발견입니다.
임신
이 부분은 send 블록에 관한 것이므로 새 체인을 만드는 것에 대한 모든 것은 범위를 벗어납니다. 사용자가 일부 원시 데이터를 보내려고 한다고 가정해 보겠습니다. 내 노드는 다음과 유사한 헤더가 있는 메시지를 생성합니다.
...
network: live
protocol version: 19
message type: publish
extensions:
block type: send
나는 700 raw의 잔액을 가진 임의의 사용자가 10 raw를 보내고 싶어하는 척 할 것입니다.
블록 정보를 자세히 살펴보면 다음과 같은 내용을 찾을 수 있습니다.
previous: BBE55A35F79F887...
link/destination: 9A2726664A18FE5...
balance: 690
work: 14b3bc748f2c8e93
signature: B421B88AFBEDFC...
잔액은 700이었기 때문에 690 raw입니다. 저는 10 raw를 보내고 있습니다.
그런 다음 노드는 이 메시지를 피어에게 보냅니다.
다른 노드가 메시지 수신
각 피어에 대해 이미 설정된 TCP 연결이 있으며 메시지가 처리된 후 새 메시지 수신기가 생성됩니다.
이것은 bootstrap_server.cpp:151
에 리스너를 설치하는 방법입니다.
void nano::bootstrap_server::receive ()
{
// ...
socket->async_read (receive_buffer, 8, [this_l](boost::system::error_code const & ec, size_t size_a) {
// ...
// Receive header
this_l->receive_header_action (ec, size_a);
});
}
TCP 연결을 통해 수신한 모든 것을 receive_buffer
에 넣습니다.
함수receive_header_action
는 바로 뒤에 있으며 다음과 같이 읽습니다.
void nano::bootstrap_server::receive_header_action (boost::system::error_code const & ec, size_t size_a)
{
if (!ec)
{
// ...
nano::bufferstream type_stream (receive_buffer->data (), size_a);
auto error (false);
nano::message_header header (error, type_stream);
if (!error)
{
auto this_l (shared_from_this ());
switch (header.type) {...}
}
}
else
{
// error management ...
}
}
위에서 일어나는 일은 receive_buffer
의 헤드가 type_stream
에 할당되고 type_stream
가 message_header
클래스를 인스턴스화하는 데 사용된다는 것입니다. 생성자의 논리는 스트림을 역직렬화하고 특히 header.type
속성을 채웁니다. 오류가 발생하지 않은 경우 다음에 수행할 작업은 header.type
(스위치 구성)에 의존하기 때문입니다. 게시 메시지의 경우를 살펴보겠습니다.
case nano::message_type::publish:
{
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
this_l->receive_publish_action (ec, size_a, header);
});
break;
}
동일한 버퍼에 다른 수신기를 설치하고 있습니다. 핸들러는 동일한 파일에서 receive_publish_action
함수를 호출하여 전달된 블록의 작업을 확인합니다. 그런 다음 메시지를 requests
데크에 추가합니다. 이것은 궁극적으로 request_response_visitor
메시지를 entries
의 tcp_message_manager
데크에 넣습니다.
메시지 항목 처리
이때 network
클래스가 스테이지에 진입합니다. 초기화되면 이 클래스는 process_messages
에서 tcp.cpp:279
루프를 실행합니다.
void nano::transport::tcp_channels::process_messages ()
{
while (!stopped) // while we are not shutting down the node
{
auto item (node.network.tcp_message_manager.get_message ());
if (item.message != nullptr)
{
process_message (*item.message, item.endpoint, item.node_id, item.socket, item.type);
}
}
}
내부적으로 process_message
메시지 발신자와 채널이 열려 있는지 확인합니다. 그런 다음 채널을 기준으로 network_message_visitor
를 생성하고 network.cpp
에서 다음 기능에 따라 게시 메시지를 처리합니다.
void publish (nano::publish const & message_a) override
{
// ... logging and monitoring logic ...
if (!node.block_processor.full ())
{
node.process_active (message_a.block);
}
// ...
}
여기서 process_active
는 메시지 내부의 블록을 block_arrival
및 block_processor
둘 다에 추가합니다. 후자는 블록을 block
대기열에 넣는 역할을 합니다.
블록 처리
node
클래스가 인스턴스화될 때마다 블록 프로세서 스레드가 생성됩니다. 이 스레드는 blockprocessor.cpp
함수 내부에 process_blocks
무한 루프를 가지고 있습니다. 이것은 다양한 잠금을 획득한 후 블록 배치를 처리하는 트랜잭션을 시작합니다. 단일 블록의 처리는 process_one
함수에 정의되어 있으며 적어도 관심 있는 전송 블록에 대해 ledger_processor
에 정의된 ledger.cpp
에 의존합니다.
전체 논리는 ledger.cpp
함수의 send_block
에서 찾을 수 있습니다. 그 핵심은 잘못될 수 있는 모든 가능한 일을 설명하려고 하는 if의 피라미드입니다. 예를 들어 블록의 작업이 충분한 경우(다른 노드에서 블록을 받았을 때 이미 확인했음을 참고하십시오).
피라미드의 꼭대기에서 우리는 마침내 명령을 실행합니다.
ledger.store.block_put (transaction, hash, block_a);
영구 저장소에 블록을 물리적으로 추가합니다.
결론
이것이 이 블록의 수명이 끝나는 것이 아닙니다. 실제로 블록이 접합되면 종료됩니다. 결합은 합의를 포함하는 다른 프로세스이므로 이중 지출로 감지되는 경우 블록이 삭제될 수도 있습니다. 나는 다른 기사에서 이것에 대해 쓸 것입니다.
Reference
이 문제에 관하여(나노 네트워크에서 송신 블록의 수명 주기 자세히 살펴보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/gurghet/a-closer-look-at-the-lifecycle-of-a-send-block-in-the-nano-network-1925
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
A bystander look at the C++ reference implementation
...
network: live
protocol version: 19
message type: publish
extensions:
block type: send
previous: BBE55A35F79F887...
link/destination: 9A2726664A18FE5...
balance: 690
work: 14b3bc748f2c8e93
signature: B421B88AFBEDFC...
void nano::bootstrap_server::receive ()
{
// ...
socket->async_read (receive_buffer, 8, [this_l](boost::system::error_code const & ec, size_t size_a) {
// ...
// Receive header
this_l->receive_header_action (ec, size_a);
});
}
void nano::bootstrap_server::receive_header_action (boost::system::error_code const & ec, size_t size_a)
{
if (!ec)
{
// ...
nano::bufferstream type_stream (receive_buffer->data (), size_a);
auto error (false);
nano::message_header header (error, type_stream);
if (!error)
{
auto this_l (shared_from_this ());
switch (header.type) {...}
}
}
else
{
// error management ...
}
}
case nano::message_type::publish:
{
socket->async_read (receive_buffer, header.payload_length_bytes (), [this_l, header](boost::system::error_code const & ec, size_t size_a) {
this_l->receive_publish_action (ec, size_a, header);
});
break;
}
void nano::transport::tcp_channels::process_messages ()
{
while (!stopped) // while we are not shutting down the node
{
auto item (node.network.tcp_message_manager.get_message ());
if (item.message != nullptr)
{
process_message (*item.message, item.endpoint, item.node_id, item.socket, item.type);
}
}
}
void publish (nano::publish const & message_a) override
{
// ... logging and monitoring logic ...
if (!node.block_processor.full ())
{
node.process_active (message_a.block);
}
// ...
}
ledger.store.block_put (transaction, hash, block_a);
Reference
이 문제에 관하여(나노 네트워크에서 송신 블록의 수명 주기 자세히 살펴보기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gurghet/a-closer-look-at-the-lifecycle-of-a-send-block-in-the-nano-network-1925텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)