Plasma Cash 계약 해독
Plasma Cash 계약 해독
모든 Plasma 체인 은 거래 순서 에 관 한 정 보 를 하나의 해시 값 으로 환산 하여 루트 체인 에 저장 합 니 다.비트 코 인과 이 더 리 움 은 모두 루트 체인 에 속한다. 이 두 블록 체인 은 매우 높 은 안전성 을 가지 고 탈 중심 화 를 통 해 (안전성 과 활성) 을 확보 했다.
Plasma 디자인 모델 은 두 가지 주요 한 부분 이 있 는데 그것 이 바로 Plasma MVP 와 Plasma Cash 이다.여기 서 우 리 는 스마트 플 라 즈 마 가 실현 한 플 라 즈 마 캐 시 계약 을 연구 하고 계약 분석 을 통 해 플 라 즈 마 캐 시 에 관 한 일련의 의문 에 대답 합 니 다.
1. 계약 코드
SmartPlasma 의 계약 코드 는 계속 업 그 레이 드 될 것 입 니 다. 저 는 그들 이 오늘 (2018 - 09 - 14) 최신 버 전에 대해 분석 을 했 습 니 다. 이 코드 는 현재 제 github 에 저 장 된 plasma cash 입 니 다.
2. 계약서 에 대한 간단 한 소개
폴 더 에는 Plasma Cash 와 무관 한 계약 이 적지 않 습 니 다. 여 기 는 Plasma Cash 와 직접 관련 된 계약 에 만 관심 을 가지 고 있 습 니 다. 예 를 들 어 ERC 20 Token 과 관련 된 계약 은 무시 하고 스스로 확인 합 니 다.
Plasma Cash 는 피 드 체인 구조 로 Plasma Cash 는 이 더 리 움 의 하 나 는 = 간단 한 UTXO 모델 을 바탕 으로 하 는 서브 체인 이 라 고 볼 수 있다.
3.1 Plasma Cash 의 자산
Plasma Cash 의 자산 은 모두 이 더 리 움 에서 나 왔 지만 Plasma Cash 에 들 어가 면 유일한 ID 를 가지 고 분할 할 수 없습니다. Mediator. sol 의 deposit 함 수 를 참고 할 수 있 습 니 다. Mediator 는 Plasma Cash 자산 을 보관 하 는 곳 입 니 다.
/** @dev Adds deposits on Smart Plasma.
* @param currency Currency address.
* @param amount Amount amount of currency.
*/
function deposit(address currency, uint amount) public {
require(amount > 0);
Token token = Token(currency);
token.transferFrom(msg.sender, this, amount); /// deposit test1
bytes32 uid = rootChain.deposit(msg.sender, currency, amount); /// deposit test2
cash[uid] = entry({
currency: currency,
amount: amount
});
}
계약 을 통 해 알 수 있 듯 이 Plasma Cash 에 들 어간 자산 은 반드시 ERC 20 Token 이 어야 한다. 이런 자산 은 실제 적 으로 Mediator 라 는 계약 에 존재 한 다음 에 Root Chain 이 그 에 게 유일한 ID, 즉 uid 를 분배 해 야 한다. 이 uid 는 어떤 token 을 대표 하 는 지, 몇 개가 있 는 지 를 나타 낸다.
3.2 Plasma Cash 에서 의 거래
키 코드 는 Transaction. sol 에 있 습 니 다.
struct Tx {
uint prevBlock;
uint uid;
uint amount;
address newOwner;
uint nonce;
address signer;
bytes32 hash;
}
여 기 는 분명 하지 않 을 수 있 습 니 다. 설명 이 필요 해 야 UTXO 거래 모델 임 을 알 수 있 습 니 다. 이 안의 amount 와 hash 는 실제 적 으로 다소 수 다스 러 워 서 무시 할 수 있 습 니 다. 그러면 나머지 멤버 들 은 설명 이 필요 합 니 다.
prevBlock
바로 UTXO 의 입력 입 니 다. 어느 부분 에서 왔 습 니까? 비트 코 인 과 같은 OutPoint 구조 가 없 는 이 유 는 TxHash + Index 입 니 다. 나중에 말씀 드 리 겠 습 니 다. uid
거래 된 자산 ID newOwner
거래 가 누구 에 게 수출 되 는 지 에 대해 서도 비트 코 인 과 같은 스 크 립 트 를 지원 하지 않 습 니 다. nonce
이 자산 의 몇 번 째 거래 입 니까?쌍 화 증명 에 중요 한 역할 을 한다. signer
자산 원 소유자 의 서명 이 있어 야 한다.amount
중요 하지 않 은 것 은 자산 을 분할 할 수 없 기 때문에 이곳 의 Amount 는 거래 에 따라 변화 가 발생 하지 않 고 hash
는 직접 계산 할 수 있다.3.3 Plasma Cash 의 Block
만약 에 일반 블록 체인 중의 Block 과 같다 면 그 는 거래 의 집합 이다. 그러나 일반 체인 과 달리 이 안의 광부 (Operator 가 아니 라) 는 서브 체인 을 잘 유지 해 야 할 뿐만 아니 라 모든 Block 에 대응 하 는 메 르 켈 나무 뿌리 를 이 더 리 움 에 주기 적 으로 저장 해 야 한다. 이 작업 은 Operator 만 완성 할 수 있다. 구체 적 인 코드 는 RootChain. sol 을 볼 수 있다.
function newBlock(bytes32 hash) public onlyOperator {
blockNumber = blockNumber.add(uint256(1));
childChain[blockNumber] = hash;
NewBlock(hash);
}
거래 증거 제출 자 는 Operator, 즉 계약 의 창시자 일 수 있 습 니 다. 이 Operator 는 일반 계좌 일 수도 있 습 니 다. 이때 그 가 바로 이 서브 체인 의 관리자 일 수도 있 고 계약 일 수도 있 습 니 다. 그러면 계약 을 통 해 서브 체인 의 블록 규칙 을 규정 할 수 있 습 니 다.
3.4 Plasma Cash 에서 자산 의 회귀 메 인체 인 이 더 리 움
자산 이 Plasma 에서 한동안 거래 된 후에 소지 자 Bob 이 Plasma Cash 서브 체인 에서 탈퇴 하려 면 이 더 리 움 계약, 즉 Root Chain 에 이 자산 을 가지 고 있다 는 것 을 증명 해 야 한다.
3.4.1 자산 보유 증명서
이 사고방식 은 UTXO 의 사고방식 과 같다. Bob 은 이 자산 이 어디에서 나 에 게 넘 어 왔 는 지 증명 할 수 있다. 구체 적 으로 RootChain. sol 중의
startExit
함 수 를 볼 수 있다. 그 사고방식 은 매우 간단 하고 증명 할 수 있다./** @dev Starts the procedure for withdrawal of the deposit from the system.
* @param previousTx Penultimate deposit transaction.
* @param previousTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
* @param previousTxBlockNum The number of the block in which the penultimate transaction is included.
* @param lastTx Last deposit transaction.
* @param lastTxProof Proof of inclusion of a last transaction in a Smart Plasma block.
* @param lastTxBlockNum The number of the block in which the last transaction is included.
*/
function startExit(
bytes previousTx,
bytes previousTxProof,
uint256 previousTxBlockNum,
bytes lastTx,
bytes lastTxProof,
uint256 lastTxBlockNum
)
public
{
Transaction.Tx memory prevDecodedTx = previousTx.createTx();
Transaction.Tx memory decodedTx = lastTx.createTx();
// prevBlock Alice uid
require(previousTxBlockNum == decodedTx.prevBlock);
require(prevDecodedTx.uid == decodedTx.uid);
//amount ,
require(prevDecodedTx.amount == decodedTx.amount);
//Alice ,
require(prevDecodedTx.newOwner == decodedTx.signer);
require(decodedTx.nonce == prevDecodedTx.nonce.add(uint256(1))); //
// Bob,
require(msg.sender == decodedTx.newOwner);
require(wallet[bytes32(decodedTx.uid)] != 0);
bytes32 prevTxHash = prevDecodedTx.hash;
bytes32 prevBlockRoot = childChain[previousTxBlockNum];
bytes32 txHash = decodedTx.hash;
bytes32 blockRoot = childChain[lastTxBlockNum];
require(
prevTxHash.verifyProof(
prevDecodedTx.uid,
prevBlockRoot,
previousTxProof
)
);
require(
txHash.verifyProof(
decodedTx.uid,
blockRoot,
lastTxProof
)
);
/// Record the exit tx.
require(exits[decodedTx.uid].state == 0);
require(challengesLength(decodedTx.uid) == 0);
exits[decodedTx.uid] = exit({
state: 2,
exitTime: now.add(challengePeriod),
exitTxBlkNum: lastTxBlockNum,
exitTx: lastTx,
txBeforeExitTxBlkNum: previousTxBlockNum,
txBeforeExitTx: previousTx
});
StartExit(prevDecodedTx.uid, previousTxBlockNum, lastTxBlockNum);
}
코드 의 절반 은
lastTxBlockNum
에 있 을 때 자산 uid 가 Bob 에 게 있다 는 것 을 증명 하 는 데 사 용 됩 니 다. 그리고 절반 은 Bob 이 자산 uid 를 가 져 가 려 고 합 니 다. 제 생각 은 계약 에 잠시 보관 하고 다른 사람 이 도전 하 기 를 기다 리 겠 습 니 다.3.4.2 다른 사람 이 나 에 게 도전 하 기 를 기다린다.
이상 의 정보 가 있 으 면 N 블록 에 있 을 때 이 자산 은 Bob 이 사용 한 것 임 을 증명 할 수 있 습 니 다. 그러나 이것 은 분명 부족 합 니 다. 현재 자산 이 Bob 에 속 한 다 는 것 을 증명 할 수 없고 Alice 가 M 블록 이후 에 다른 사람 에 게 주지 않 았 다 는 것 을 증명 할 수 없습니다. M 블록 에 있 을 때 Alice 가 정말 uid 의 소유자 라 는 것 을 증명 할 수 없습니다.이런 문제 들 은 대답 하기 어 려 울 것 같 지만 사실은 생각 도 간단 하 다. 이 생각 은 뇌 전 네트워크 에서 문 제 를 해결 하 는 방법 과 똑 같 아서 이 자산 의 이해관계 자 를 나서서 증 거 를 제시 하 게 한다. 예 를 들 어 캐 롤 이 이 자산 Bob 을 입증 할 수 있다 면 사실은 Bob 은 쌍 화 이다. 구체 적 인 도전 과 영전 코드 가 비교적 복잡 하 다.그러나 이것 도 Plasma Cash 의 핵심 안전성 이다. 이런 것들 이 없 으 면 모든 참여 자 들 이 자신의 권익 을 보장 할 수 없다.
//challengeExit uid Bob
/** @dev Challenges a exit.
* @param uid Unique identifier of a deposit.
* @param challengeTx Transaction that disputes an exit.
* @param proof Proof of inclusion of the transaction in a Smart Plasma block.
* @param challengeBlockNum The number of the block in which the transaction is included.
*/
function challengeExit(
uint256 uid,
bytes challengeTx,
bytes proof,
uint256 challengeBlockNum
)
public
{
require(exits[uid].state == 2);
Transaction.Tx memory exitDecodedTx = (exits[uid].exitTx).createTx();
Transaction.Tx memory beforeExitDecodedTx = (exits[uid].txBeforeExitTx).createTx();
Transaction.Tx memory challengeDecodedTx = challengeTx.createTx();
require(exitDecodedTx.uid == challengeDecodedTx.uid);
require(exitDecodedTx.amount == challengeDecodedTx.amount);
bytes32 txHash = challengeDecodedTx.hash;
bytes32 blockRoot = childChain[challengeBlockNum];
require(txHash.verifyProof(uid, blockRoot, proof));
// test challenge #1 & test challenge #2 , Bob
if (exitDecodedTx.newOwner == challengeDecodedTx.signer &&
exitDecodedTx.nonce < challengeDecodedTx.nonce) {
delete exits[uid];
return;
}
// test challenge #3, , Alice , Carol BlockNumer , .
if (challengeBlockNum < exits[uid].exitTxBlkNum &&
(beforeExitDecodedTx.newOwner == challengeDecodedTx.signer &&
challengeDecodedTx.nonce > beforeExitDecodedTx.nonce)) {
delete exits[uid];
return;
}
// test challenge #4 M , ,Alice M uid
if (challengeBlockNum < exits[uid].txBeforeExitTxBlkNum ) {
exits[uid].state = 1;
addChallenge(uid, challengeTx, challengeBlockNum);
}
require(exits[uid].state == 1);
ChallengeExit(uid);
}
//Bob , , , , Alice M uid
/** @dev Answers a challenge exit.
* @param uid Unique identifier of a deposit.
* @param challengeTx Transaction that disputes an exit.
* @param respondTx Transaction that answers to a dispute transaction.
* @param proof Proof of inclusion of the respond transaction in a Smart Plasma block.
* @param blockNum The number of the block in which the respond transaction is included.
*/
function respondChallengeExit(
uint256 uid,
bytes challengeTx,
bytes respondTx,
bytes proof,
uint blockNum
)
public
{
require(challengeExists(uid, challengeTx));
require(exits[uid].state == 1);
Transaction.Tx memory challengeDecodedTx = challengeTx.createTx();
Transaction.Tx memory respondDecodedTx = respondTx.createTx();
require(challengeDecodedTx.uid == respondDecodedTx.uid);
require(challengeDecodedTx.amount == respondDecodedTx.amount);
require(challengeDecodedTx.newOwner == respondDecodedTx.signer);
require(challengeDecodedTx.nonce.add(uint256(1)) == respondDecodedTx.nonce);
require(blockNum < exits[uid].txBeforeExitTxBlkNum);
bytes32 txHash = respondDecodedTx.hash;
bytes32 blockRoot = childChain[blockNum];
require(txHash.verifyProof(uid, blockRoot, proof));
removeChallenge(uid, challengeTx);
if (challengesLength(uid) == 0) {
exits[uid].state = 2;
}
RespondChallengeExit(uid);
}
3.4.3 도전 기간 이 지나 면 Bob 은 자산 uid 를 되 찾 습 니 다.
도전 기간 이 지난 후 Bob 은 Mediator. sol 에서 자산 을 이 태 방 으로 돌려 보 내 자고 제안 했다.
/** @dev withdraws deposit from Smart Plasma.
* @param prevTx Penultimate deposit transaction.
* @param prevTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
* @param prevTxBlkNum The number of the block in which the penultimate transaction is included.
* @param txRaw lastTx Last deposit transaction.
* @param txProof Proof of inclusion of a last transaction in a Smart Plasma block.
* @param txBlkNum The number of the block in which the last transaction is included.
*/
function withdraw(
bytes prevTx,
bytes prevTxProof,
uint prevTxBlkNum,
bytes txRaw,
bytes txProof,
uint txBlkNum
)
public
{
bytes32 uid = rootChain.finishExit(
msg.sender,
prevTx,
prevTxProof,
prevTxBlkNum,
txRaw,
txProof,
txBlkNum
);
entry invoice = cash[uid];
Token token = Token(invoice.currency);
token.transfer(msg.sender, invoice.amount); ///
delete(cash[uid]);
}
RootChain 재 검증
/** @dev Finishes the procedure for withdrawal of the deposit from the system.
* Can only call the owner. Usually the owner is the mediator contract.
* @param account Account that initialized the deposit withdrawal.
* @param previousTx Penultimate deposit transaction.
* @param previousTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
* @param previousTxBlockNum The number of the block in which the penultimate transaction is included.
* @param lastTx Last deposit transaction.
* @param lastTxProof Proof of inclusion of a last transaction in a Smart Plasma block.
* @param lastTxBlockNum The number of the block in which the last transaction is included.
*/
function finishExit(
address account,
bytes previousTx,
bytes previousTxProof,
uint256 previousTxBlockNum,
bytes lastTx,
bytes lastTxProof,
uint256 lastTxBlockNum
)
public
onlyOwner
returns (bytes32)
{
Transaction.Tx memory prevDecodedTx = previousTx.createTx();
Transaction.Tx memory decodedTx = lastTx.createTx();
require(previousTxBlockNum == decodedTx.prevBlock);
require(prevDecodedTx.uid == decodedTx.uid);
require(prevDecodedTx.amount == decodedTx.amount);
require(prevDecodedTx.newOwner == decodedTx.signer);
require(account == decodedTx.newOwner);
bytes32 prevTxHash = prevDecodedTx.hash;
bytes32 prevBlockRoot = childChain[previousTxBlockNum];
bytes32 txHash = decodedTx.hash;
bytes32 blockRoot = childChain[lastTxBlockNum];
require(
prevTxHash.verifyProof(
prevDecodedTx.uid,
prevBlockRoot,
previousTxProof
)
);
require(
txHash.verifyProof(
decodedTx.uid,
blockRoot,
lastTxProof
)
);
require(exits[decodedTx.uid].exitTime < now); //
require(exits[decodedTx.uid].state == 2); //
require(challengesLength(decodedTx.uid) == 0);
exits[decodedTx.uid].state = 3;
delete(wallet[bytes32(decodedTx.uid)]);
FinishExit(decodedTx.uid);
return bytes32(decodedTx.uid);
}
4. Plasma Cash 의 종료 예시
sequenceDiagram participant o as operator participant u1 as alice participant u2 as bob participant u3 as carol participant u4 as david u1 - > > rootchain: deposit asset to RootChain, get unique id asset 1 o - > rootchain: 생 성 NewBlock 3, 기록 이 자산 u1 - > > u2: transfer asset 1 to bob o - > > rootchain: 생 성 NewBlock 7,이 거래 u1 - > u3: transfer asset 1 to carol o - > rootchain: Newblock 11 을 생 성하 여 이 거래 u3 - > rootchain 을 기록 합 니 다. 저 는 asset 1 을 메 인 체인 으로 인출 하고 asset 1 을 alice 에서 제공 하 며 alice 에서 서명 하여 11 u2 - > rootchain 에서 발생 합 니 다. 도전 을 제기 합 니 다. asset 1 은 저 에 게 속 해 야 합 니 다. asset 1 을 제공 하고 alice 에서 서명 하 며 7 에서 발생 합 니 다. rootchain 은 bob 증거 가 유효 하 다 고 판단 합 니 다.carol 현금 인출 거부 u2 - > u4: transfer asset 1 to devid o - > rootchain: Newblock 27 생 성, 이 거래 기록 u4 - > rootchain: 현금 인출 asset 1, bob 에서 왔 습 니 다. bob 의 서명 이 있 습 니 다. 27 loop David wait for challenge u4 - > u4: 도전 기 2 주 동안 end u4 - > rootchain: withdraw, 현금 인출, asset 1 을 rootchain 에서 전환 합 니 다.
5. 기타 문제
다음으로 전송:https://www.cnblogs.com/baizx/p/9649153.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.