DoubleZero의 소프트웨어는 출시 당시부터 중앙 집중식 요소를 포함하고 있습니다. 오프체인 개인 키는 핵심 스마트 계약을 제어하며, 온체인에 없는 시스템의 필수 부분을 실행하는 데 필요합니다.
DoubleZero는 미국 증권거래위원회(SEC)의 무조치 서한을 통해 DoubleZero 네트워크 참여자에게 지급되는 2Z 토큰이 증권법에 따른 등록 요건의 적용을 받지 않는다고 밝혔습니다. 그러나 이러한 설명은 실제 시스템 운영 방식과 일치하지 않는 것으로 보입니다.
DoubleZero가 SEC로부터 받은 면책 처분은 현재 운영 중인 시스템과 일치하지 않는 진술에 근거한 것으로 보입니다. 실제로 배포된 시스템은 DoubleZero 팀이 SEC와 대중에게 제시했던 진술과 상당한 차이가 있습니다.
SEC의 서한은 DoubleZero의 요청서에 명시된 내용과 일관되게 작동하는 시스템에만 적용됩니다. 실제 DoubleZero 시스템이 해당 서한의 내용과 일치하지 않는 부분에 대해서는 어떠한 구제 조치도 허용되지 않았습니다.
우리는 이전에 DoubleZero의 무조치 서한 요청과 관련된 이러한 문제점들에 대해 언급한 바 있습니다 .
이제 DoubleZero의 모든 소프트웨어 코드가 공개되었으므로, DoubleZero가 SEC에 제출한 면책 요청서에서 주장했던 내용과 실제 구현된 방식이 어떻게 다른지 살펴보겠습니다.
이것은 N의 1부입니다. DoubleZero는 복잡한 회사이며, DoubleZero가 SEC에 제출한 진술과 관련된 단 하나의 문제만으로도 SEC의 면책 조치가 적용되지 않을 수 있습니다.
센티넬
시스템 아키텍처 다이어그램에는 이 구성 요소가 "로 표시되어 있지 않습니다."
"보초":

하지만 해당 다이어그램에는 "DZ 리소스 기여자"라고 표시된 부분이 있고, "DoubleZero에서 연결 요청 시작" 아래의 지침을 읽어보면 다음과 같은 내용이 있습니다.
`request-validator-access` 명령어를 사용하여 연결 요청에 대한 솔라나(Solana) 계정을 생성하십시오. DoubleZero Sentinel 에이전트는 새 계정을 감지하고 해당 계정의 신원과 서명을 검증한 후 DoubleZero에 액세스 패스를 생성하여 서버가 연결을 설정할 수 있도록 합니다.
Sentinel 에이전트는 액세스 요청을 감시하고 아키텍처 다이어그램의 왼쪽 상단에 설명된 기능에 따라 해당 요청을 실행합니다.
알고 보니, 센티넬 코드는 DoubleZero Foundation 산하의 GitHub 저장소인 doublezero-offchain 에 있습니다. 이 저장소는 "DoubleZero 네트워크를 위한 오프체인 구성 요소"로 설명되어 있으며, "DZ 리소스 기여자"와도 관련이 있을 것입니다. 다시 말하지만, 저장소 이름과 다이어그램 이름이 상당히 겹칩니다.
해당 코드를 살펴보면 Sentinel에서 "keypair" 변수를 찾을 수 있습니다.
/// 솔라나(Solana) 패스포트 프로그램에서 승인된 키 쌍 파일의 경로
/// 그리고 온보딩 DZ 원장 자금을 보유하여 승인된 검증자에게 크레딧을 제공합니다.
키 쌍: PathBuf,
해당 키 쌍은 솔라나(Solana) 액세스를 설정하는 데 사용되며 PollingSentinel 이라는 소프트웨어 객체를 실행합니다.
let sentinel = PollingSentinel {
dz_rpc_client: DzRpcClient::new(dz_rpc, keypair.clone(), serviceability_id),
sol_rpc_client: SolRpcClient::new(sol_rpc, keypair),
처리된 캐시: Arc::new(Cache::new()),
poll_interval: Duration::from_secs(15),
이전 리더 시대: 0,
};RPC 클라이언트가 키 쌍을 사용한다는 점에 유의하세요. RPC는 원격 프로시저 호출(Remote Procedure Call)의 약자입니다. 이는 웹3에만 있는 새로운 기술이 아니라 오래전부터 사용되어 왔습니다. RPC는 한 컴퓨터가 다른 곳에 있는 함수를 호출하는 방식입니다.
이 경우 우리가 살펴보는 코드는 블록체인 상에 존재하는 함수들을 호출합니다. 블록체인은 개인 키를 중심으로 구축되며, 개인 키를 소유하는 것이 소유권 또는 제어권을 의미한다는 개념에 기반합니다. 센티넬에서 이루어지는 RPC 호출은 이러한 소유권 또는 제어권을 전달하는 개인 키를 사용합니다. 이는 블록체인 시스템에 맞게 적용된 표준 소프트웨어 엔지니어링 패턴을 따르는 것입니다.
이렇게 하면 무슨 일이 일어날까요?
PollingSentinel은 이름에서 알 수 있듯이 다음과 같은 새로운 액세스 요청을 확인하는 루프를 실행합니다 .
new_requests의 access_id에 대해 {
request_pda = access_id.request_pda로 설정합니다.
self.handle_access_request(access_id).await { 와 일치합니다.
Ok(_) => {
// 처리 성공 후에만 캐시합니다.
self.processed_cache.insert(request_pda, Instant::now(), CACHE_TTL).await;
}
오류(err) => {
오류!(?err, "네트워크 액세스 요청 유효성 검사 중 오류가 발생했습니다. 다음 폴링 시 다시 시도합니다.");
// 실패를 캐시하지 말고 다음 폴링 주기에서 재시도하도록 합니다.
}
}
}이 기능이 어떻게 작동하는지 설명하기 위해 대표적인 코드 부분을 발췌했습니다.
이는 함수의 중간 부분에서 코드 블록을 추출하는 것을 의미합니다. Rust의 일부 설정 코드는 적절한 도구 없이는 분석하기 어려울 수 있으므로 핵심 로직에 집중합니다.
PollingSentinel은 액세스 요청을 감시하고 명령줄에서 전달된 개인 키를 사용하여 handle_access_request 함수를 통해 요청을 처리합니다. 이 함수는 이름에서 알 수 있듯이 액세스 요청을 처리합니다.
코드를 이해하지 못하더라도 주석과 로그 메시지를 통해 이해할 수 있습니다.
async fn handle_access_request(&self, access_id: AccessId) -> Result<()> {
let service_key = match &access_id.mode {
AccessMode::SolanaValidator(a) => a.service_key,
AccessMode::SolanaValidatorWithBackupIds { attestation, .. } => attestation.service_key,
};
정보!(%service_key, request_pda = %access_id.request_pda, "접근 요청 처리 중");
let validator_ips = self.verify_qualifiers(&access_id.mode).await?;
validator_ips.is_empty()가 아닌 경우 {
// 모든 검증자(기본 + 백업)에게 접근 권한을 발급합니다.
validator_id와 validator_ip가 validator_ips에 대해 각각 {
rpc_with_retry(
|| 비동기 {
self.dz_rpc_client
.issue_access_pass(&service_key, &validator_ip, &validator_id)
.기다리다
},
"접근번호 문제",
)
.기다리세요?;
정보!(%validator_id, %validator_ip, 사용자 = %service_key, "액세스 패스 발급됨");
}
let signature = rpc_with_retry(
|| 비동기 {
self.sol_rpc_client
.grant_access(&access_id.request_pda, &access_id.rent_beneficiary_key)
.기다리다
},
"접근 권한 부여",
)
.기다리세요?;
정보!(%서명, 사용자 = %서비스_키, "액세스 요청 승인됨");
metrics::counter!("doublezero_sentinel_access_granted").increment(1);
} 또 다른 {
let signature = rpc_with_retry(
|| 비동기 {
self.sol_rpc_client
.접근 거부(&access_id.request_pda)
.기다리다
},
"접근 거부",
)
.기다리세요?;
정보!(%서명, 사용자 = %서비스_키, "액세스 요청 거부됨");
metrics::counter!("doublezero_sentinel_access_denied").increment(1);
}
좋아요(())
}여기서 중요한 점은 "접근 요청 처리"에는 여러 로직이 포함되어 있으며, 이 과정에는 항상 여러 RPC 호출이 수반된다는 것입니다. 이러한 RPC 호출은 솔라나(Solana) 또는 더블제로(DoubleZero) 블록체인에 있는 함수들을 호출하는 것입니다.
네, 맞습니다. DoubleZero는 솔라나(Solana) 와 솔라나(Solana) 포크(Fork) 자체 DoubleZero Ledger , 그리고 오프체인 종속성을 혼합하여 운영됩니다.
해당 함수에서 dz_rpc_client(DZ 체인) 및 sol_rpc_client( 솔라나(Solana))를 호출할 때 사용하는 함수들은 패스포트 프로그램에 접근 권한을 부여하는 개인 키로 서명됩니다. 따라서 이 코드가 grant_access(), issue_access_pass() 등의 파생 상품 호출할 때, 모든 작업은 Sentinel을 실행하는 주체가 올바른 개인 키에 접근 권한을 가지고 있어야만 가능합니다. 이 프로세스는 개인 키에 의해 제어되므로 에르고(Ergo) 집중식입니다. 이러한 특정 개인 키 없이는 Sentinel을 정상적으로 실행할 수 없습니다.
앞서 언급했던 " 솔라나(Solana) 패스포트 프로그램에서 승인된 키 쌍 파일"을 기억하시나요? 이는 특수 키에 대한 정보를 알고 있는 패스포트 프로그램이 어딘가에 존재한다는 것을 의미합니다. 실제로 그런 프로그램이 있습니다. 살펴보면 패스포트 프로그램 측에서도 이러한 중앙 제어 기능을 확인할 수 있습니다. 다음은 패스포트 프로그램 내에서 접근 요청을 처리하는 코드 의 일부입니다. 이는 앞서 언급한 RPC 호출의 반대쪽 부분입니다.
// 계정 0은 프로그램 구성이어야 합니다.
// 계정 1은 DoubleZero Ledger 센티널이어야 합니다.
//
// 이 호출은 DoubleZero Ledger 센티널이 서명자인지 확인합니다.
// 동일한 센티널이 프로그램 설정에 인코딩되어 있습니다.
let authorized_use =
VerifiedProgramAuthority::try_next_accounts(&mut accounts_iter, Authority::Sentinel)?;
이 코드는 센티넬(앞서 설명한 오프체인 구성 요소)이 요청 시작에 관여했는지 확인합니다. 또한 센티넬이 "[패스포트] 프로그램 구성에 인코딩되어 있는지"를 검사합니다. 이는 개방형 비허가형(Permissionless) 시스템과 일치하지 않습니다. 이 코드는 특정 개인 키가 개방형 비허가형(Permissionless) 네트워크라고 주장하는 네트워크에 대한 접근 요청을 시작하는 데 사용되었는지 확인하는 상호 연관된 검사 기능을 포함합니다. 이러한 개인 키는 온보딩 프로세스에 대한 독점적인 제어 권한을 제공합니다.
추가 코드를 검토하는 대신 DoubleZero의 공식 문서를 참조하면 됩니다. 문서에는 명확하게 설명되어 있습니다.
서비스 키는 기여자가 DoubleZero 재단에 인증을 위해 제출하기 전에 생성하여 안전하게 보관해야 합니다. 이를 통해 모든 CLI 상호 작용을 암호화 방식으로 검증하고 올바른 기여자 계정과 연결할 수 있습니다. [ 여기 ]
"RPC 노드의 경우 IBRL 모드에서 DoubleZero에 연결하는 방법 "의 2단계는 다음과 같습니다.
2. 더블제로 재단에 연락하세요
DoubleZero 재단입니다. DoubleZeroID, 검증자 ID(노드 ID), 그리고 접속에 사용할 공용 IPv4 주소를 제공해야 합니다.
문서에는 사용자가 연결 과정의 일부로 DoubleZero 재단에 연락해야 한다고 명시되어 있습니다. 이러한 요구 사항은 비허가형(Permissionless) 시스템과 일치하지 않습니다.
더블제로의 공식적인 정책이 이 과정에 대해 '재량권을 행사하지 않는다'는 것이라 하더라도, 재단은 여전히 이 과정에 대한 통제권을 보유하고 있습니다.
문서와 코드를 종합해 보면 다음과 같은 사실이 입증됩니다.
- 코드 내에 " 솔라나(Solana) 패스포트 프로그램에서 승인된 키 쌍 파일"을 직접 참조하는 부분이 있으며, 이 코드는 해당 패스포트 프로그램과 특권적인 방식으로 상호 작용합니다.
- 재단이 "승인"을 한다는 명확한 진술
- 사용자가 재단에 "DoubleZeroID, 검증자 ID(노드 ID) 및 접속에 사용할 공용 IPv4 주소를 제공"해야 한다는 요구 사항입니다.
문서만 봐도 코드를 분석하는 능력과 관계없이 이 사실이 명확해집니다.
팀이 SEC에 제출한 진술서 자체에서도 이러한 문제들을 잘 이해하고 있음을 알 수 있습니다.
무조치 서한
증권거래위원회(SEC)에 제출된 무조치 요청서에는 다음과 같은 내용이 포함되어 있습니다.
전반적으로 네트워크 제공업체들은 이 시스템에서 정교하고 독립적인 운영자입니다. 이들은 네트워크와의 링크 통합, 관련 FPGA 장치 설치, 서비스 수준 설정 및 충족, 링크 유지 관리, 그리고 필요에 따라 네트워크에서 연결을 끊는 것까지 모든 책임을 집니다. 네트워크 제공업체는 재단과 아무런 관련이 없으며, 재단이나 다른 어떤 기부자도 (교육 및 네트워크 제공업체 간의 조정을 제외하고는) 이들을 대신하여 이러한 업무를 수행하지 않습니다.
문서에는 해당 단락에 대한 각주도 다음과 같이 포함되어 있습니다.
재단은 네트워크 제공업체가 새로운 광섬유 링크를 네트워크에 물리적으로 연결하는 데 필요한 지원을 제한적으로 제공합니다. 재단은 이러한 서비스로 수익을 창출하지 않으며, 서비스 출시 시점에는 네트워크 제공업체 선정에 대한 재량권을 행사하지 않습니다. 재단은 향후 이 과정이 완전히 비허가형(Permissionless) 진행될 수 있도록 개선할 계획입니다.
각주에 명시된 내용은 물리적 연결 지원에만 국한되며 물리적 인프라 지원만을 다룹니다.
'물리적'이라는 개념을 논리적 연결까지 포함하는 넓은 의미로 해석하더라도, 이러한 표현 방식은 실제 시스템과 일관성이 없습니다.
이전 섹션에서는 재단이 특정 조치를 취해야만 누구나 자신의 링크를 네트워크와 통합할 수 있다고 명시했습니다.
시스템이 제대로 작동하려면 누군가가 특정 개인 키 세트를 사용하여 센티넬 프로그램을 실행해야 합니다. 이 외에 추가적인 중앙 집중화 요소가 존재하는지는 후속 분석에서 다룰 예정입니다.
그건 일단 나중에 생각해 보자.
증거에 따르면 재단은 온보딩 프로세스의 특정 핵심 단계에 대한 유일한 제공자입니다. 면책 요청은 재단이 핵심 시스템 기능의 중앙 제공자가 아니라는 점을 시사합니다. 해당 서한은 물리적 연결 지원을 명시적으로 제외하고 있으며, 궁극적으로 이러한 연결을 비허가형(Permissionless) 이용할 수 있도록 만들겠다는 의도를 언급하고 있습니다.
이 사안이 소송으로 이어질 경우, 향후 시스템 변경에 대한 진술을 근거로 면책 조치가 허용되어야 하는지에 대한 의문이 제기될 수 있습니다.
향후 의도보다는 실제로 구축된 시스템을 기준으로 규제 요건이 적용되는지 여부를 결정해야 합니다.
위 내용을 '네트워크 제공자 간의 조정'이라고 특징지을 수 있지만, 이러한 조정은 소유자의 개인 키를 통해 제어되는 계약을 통해 이루어집니다.
이러한 형태의 '조정'이 분산형으로 인정된다면, 규제 목적상 중앙 집중식 시스템과 분산형 시스템의 구분은 무의미해집니다.
코드는 어디에 있나요?
특히, 코드 및 온체인 이벤트에 대한 정보를 제공하는 블록 탐색기 링크가 없습니다. 이는 저희가 파악한 바로는 해당 코드가 솔라나(Solana) 에서 검증되지 않았고, 배포 주소 목록도 공개되어 있지 않기 때문입니다.
다음은 DoubleZero의 수익 배분 프로그램 중 하나입니다 .

해당 코드는 공개 탐색기에서 검증되지 않았습니다. 문서에는 계약 주소가 포함되어 있지 않으며, 일반적인 관행과 달리 배포 아티팩트가 저장된 저장소 위치도 제공되지 않습니다. 또한, 해당 코드는 업그레이드 가능합니다.
계약 주소는 doublezero-solana 저장소의 코드에 하드코딩되어 있으므로 우리는 이를 알 수 있습니다.
- 수익 분배: dzrevZC94tBLwuHw1dyynZxaXTWyp7yocsinyEVPtt4
- 여권: dzpt2dM8g9qsLxpdddnVvKfjkCLVXd82jrrQVJigCPV
둘 다 검증되지 않았고, 둘 다 업그레이드가 가능하지만, 어디에서도 쉽게 찾을 수 없습니다.
일반적인 관행에는 주소가 명확하게 기재된 검증된 계약서가 포함됩니다. 이러한 정보는 법규 검토를 통해 확인할 수 있지만, 표준적인 문서화 관행이 부족하다는 점은 주목할 만합니다.
논의
이 분석에 따르면 승인된 면책 조치는 배포된 DoubleZero에는 적용되지 않을 수 있습니다.
추가적인 맥락을 살펴보는 것이 중요한데, DoubleZero의 요청으로 인해 SEC 위원인 피어스가 이 모든 상황에서 SEC의 역할을 다음과 같이 설명했기 때문입니다.
우리의 임무는 혁신가들과 성실하게 소통하고, 그들이 자신의 모델이 어떻게 작동하는지 설명하는 것을 주의 깊게 경청하며, 법적 의무를 신중하고 정확하게 적용하는 것입니다.
그녀는 또한 해당 프로젝트를 "네트워크 규칙에 따라 네트워크에 참여하는 사용자에게 토큰을 프로그램 방식으로 배포하는" 프로젝트라고 설명했는데, 이는 어느 정도는 사실입니다.
하지만 재단이 배포 과정을 통제하고 있다는 점을 고려하면, 중앙집권화 수준은 기존의 중앙집권형 시스템과 유사해 보입니다.
피어스의 발언은 위에서 언급한 중앙 집중식 제어 메커니즘을 고려하지 않고 DoubleZero가 스스로를 '개방형 분산형 P2P 네트워크'라고 규정한 것을 그대로 받아들이는 것처럼 보입니다.
면책 요청 내용은 실제로 배포된 DoubleZero 시스템과 실질적으로 다른 것으로 보이지만, SEC가 면책을 승인한 후 DoubleZero는 이러한 결과를 대대적으로 홍보했습니다.
SEC에 제출된 정보가 실제 운영 시스템과 일치하지 않는다면, 이는 조치 유예 절차에 대한 의문을 제기하며, 위원회의 추가적인 설명이 필요한지에 대한 의문을 불러일으킵니다.
우리는 SEC가 검토가 아닌 정보 공개에 중점을 둔다는 것을 알고 있습니다.
우리는 SEC가 이와 같은 조치 불필요 요청이 해당 시스템과 일치하는지 여부를 검토할 것으로 기대하지 않습니다. 그것은 SEC의 업무가 아니며, 조치 불필요 서한에는 당연히 이러한 단서 조항이 포함되어 있습니다.
이 입장은 귀하께서 서신을 통해 부서에 전달하신 내용을 바탕으로 합니다. 사실관계나 상황이 다를 경우 부서는 다른 결론을 내릴 수 있습니다.
SEC의 공시 기반 접근 방식은 실질적으로 부정확한 진술을 근거로 면책 처분을 받은 상황을 다루는 것을 배제하지 않습니다.
DoubleZero는 홍보 활동에서 면책 조항에 계속 의존하고 있습니다. 향후 법적 조치가 취해질 경우, 해당 면책 조항이 현재 시스템에 적용되는지 여부에 대한 질문이 제기될 가능성이 높습니다.
현 상황이 오래 지속될수록, 아무런 조치도 취하지 않는 구제책에 대한 의존도가 더욱 깊어질 것입니다.
해당 코드는 공개되어 분석할 수 있습니다. 조치 불필요 요청과 배포된 시스템 간의 중대한 차이점을 파악할 수 있습니다.
시스템이 요청서에 명시된 내용과 다를 경우, 구제 조치가 적용되지 않을 수 있습니다. 구제 조치의 적용 가능성에 대한 팀의 주관적인 판단은 구제 조치가 적용되는지 여부에 대한 법적 문제와는 별개입니다.
중요한 것은 해당 팀이 자신들의 프로젝트와는 무관 한 면책 통지서를 제시하며, 일반인이 그러한 판단을 내릴 능력이 부족하기 때문에 명백히 거짓임을 알아차릴 수 없는 주장을 펼칠 수 있다는 점입니다.
규제 조치는 제3자 분석보다는 철저한 조사에 근거해야 합니다.
위원회가 사실관계가 진술과 다를 경우 무조치 서한의 적용 가능성에 대해 공개적으로 명확히 설명해 준다면 매우 유용할 것입니다.
면책 요청서에 포함된 허위 진술이 언제 강화된 조사를 필요로 하는지에 대한 명확한 설명은 보다 명확한 기준을 설정하는 데 도움이 될 것입니다. 이러한 설명이 없다면, 규제 준수 여부를 확인하는 면책 절차의 유용성이 저해될 수 있습니다.

DoubleZero는 중앙 집중화되어 있으며 SEC를 속였다: N부 1편은 원래 미디엄(Medium) 의 ChainArgos 에 게시되었으며, 사람들은 이 기사를 강조 표시하고 댓글을 달면서 계속해서 대화를 이어가고 있습니다.




