1658750820
이 기사에서는 Python을 MacOS 장치에 최신 버전으로 설치하고 업데이트하는 방법을 안내합니다.
공식 설치 프로그램에서 Python을 설치하는 것이 macOS에서 가장 안정적인 설치 방법입니다. 여기에는 Python으로 애플리케이션을 개발하는 데 필요한 모든 시스템 종속성이 포함됩니다.
2. 중요한 정보를 이해하고 다음 단계로 진행
3. 라이선스를 이해하고 계속하기
4. 계약 및 조건에 동의하면 동의를 선택합니다.
5. 파일을 설치할 대상을 선택하십시오. 권장 사항은 이 설치 프로그램이 선택한 기본 위치를 변경하지 않는 것입니다.
6. 설치가 시작되고 완료되면 이 메시지가 표시됩니다. 이제 Python 3.0이 컴퓨터에 설치되었으므로 이 창을 닫을 수 있습니다.
이제 MacOS 기기에서 Python을 최신 버전으로 설치하고 업데이트할 수 있습니다.
1658750820
이 기사에서는 Python을 MacOS 장치에 최신 버전으로 설치하고 업데이트하는 방법을 안내합니다.
공식 설치 프로그램에서 Python을 설치하는 것이 macOS에서 가장 안정적인 설치 방법입니다. 여기에는 Python으로 애플리케이션을 개발하는 데 필요한 모든 시스템 종속성이 포함됩니다.
2. 중요한 정보를 이해하고 다음 단계로 진행
3. 라이선스를 이해하고 계속하기
4. 계약 및 조건에 동의하면 동의를 선택합니다.
5. 파일을 설치할 대상을 선택하십시오. 권장 사항은 이 설치 프로그램이 선택한 기본 위치를 변경하지 않는 것입니다.
6. 설치가 시작되고 완료되면 이 메시지가 표시됩니다. 이제 Python 3.0이 컴퓨터에 설치되었으므로 이 창을 닫을 수 있습니다.
이제 MacOS 기기에서 Python을 최신 버전으로 설치하고 업데이트할 수 있습니다.
1614246541
Wonderful MBOX to PST transformation expresses that you frequently don’t hear in a similar sentence. Getting an ideal MBOX to PST Converter resembles a slippery dream. Numerous clients are ordinary giving a shot to locate the most ideal approach to accomplish this fantasy. Lamentably, the greater part of the apparatuses that guarantee you to help in accomplishing that fantasy is simply fabrications. They neglect to convey their guarantees, consequently, bringing about a deficient and degenerate Converter measure.
To accomplish this fantasy, you’ll need a transformation arrangement that has the capacity of assuming the difficulties of the advanced email data sets. The transformation arrangement is sponsored by the privileged mechanical progressions. Try not to stress it is a lot more straightforward than it sounds. Also, this article will help you discover one such arrangement. Peruse on and rethink the manner in which you take on your information movement measure.
The fast advancement in the mechanical world has influenced the interaction of information relocation decidedly. It has Converted the manner in which you approach the way toward moving your information. Outsider programming arrangement appeared because of this very turn of events and is presently the most prescribed answer for convert the Mbox file to pst. Your job is to locate the best outsider converter there is and you are set.
Mail Extractor Pro from MBOX to PST Converter for Mac Software is the best outsider converter apparatus undoubtedly. Suggested by top specialists and easygoing clients the same, the instrument has the correct equilibrium of the relative multitude of fundamental highlights less the intricacy that typically comes free with the apparatus. It is vigorous, exact, precise yet still exceptionally simple to utilize.
What is a transformation interaction that isn’t exact? A fiasco. The fundamental assignment of your converter instrument is to Converter over your information data with exactness and accuracy. You are indeed changing your information starting with one arrangement over then onto the next. Thus, you can’t agree to a transformation arrangement with less exactness.
You can pass judgment on the exactness of any converter device by its capacity to deal with complex Unicode information present in the information documents. Unicode information is perplexing in nature as it is not encoded like your typical text-based information. In this way, it is somewhat difficult to Converter over and numerous converter instruments neglect to manage them.
This converter device causes you to convert everything present in your information document including the Unicode information, giving you an ideal MBOX to PST transformation.
The interface is the media of correspondence of any product application. Simpler it is to utilize; simpler it will be for you to make yourself clear to the application.
With this converter device, you get free streaming astutely planned interface. It doesn’t have any perplexing and pointless highlights in plain view that may befuddle you. It just shows the highlights needed to take care of business. It even furnishes you with guidelines to assist you with your Mac MBOX to PST Converter measure.
Download the MBOX to PST converter for Mac free preliminary variant of the device now.
#mbox to pst converter for mac #mac mbox to pst converter #mac mbox to pst #mbox to pst
1598511081
Install Golang on Mac is very easy. You can download the binary from the official website or install it using homebrew. Golang provides binary distributions for Mac OS X, Windows, and Linux. Then set up your Golang environment. If you are using a different OS, you can download the Go source code and install it from the source.
#golang #mac #vscode #go #linux #mac os x
1651673644
2009年1月3日のビットコインの発売により、デジタル資産やデジタル通貨などのトレンドが動き始め、それ以来、イーサリアムやソラナなどのブロックチェーンがさらに作成されています。さまざまな機能とユースケースがありますが、これらのブロックチェーンには1つの共通点があります。それらは、規制当局なしで民主的に運営するように設計されました。したがって、このモデルは、データの機密性を保持し、信頼できる関係者間で共有する必要がある規制対象の業界には適していません。このため、プライベートブロックチェーンが存在します。
プライベートブロックチェーンは、許可されたブロックチェーンです。プライベートブロックチェーンには、ネットワークを制御し、他のノードのアクセス許可とアクセス制御を構成できるネットワークオペレーターと呼ばれるエンティティが含まれています。プライバシーと信頼を維持するために、トランザクションに参加しているエンティティのみがそれについての知識を持ち、他のエンティティはそれにアクセスできません。
プライベートブロックチェーンを利用するデジタルプラットフォームの例としては、Hyperledger Fabric、Ripple、R3のCordaなどがあります。この記事では、Cordaを探索し、CorDappsの作成方法を学びます。始めましょう!
Cordaは、規制市場でのアプリケーションの開発を容易にする、許可されたピアツーピア(P2P)分散型台帳テクノロジー(DLT)です。Cordaを使用すると、当事者は、ネットワーク参加者の識別に自信を持ちながら、単一のオープンネットワークで相互に自由に発見して取引することができます。
長期的には、Cordaは世界中で共有される分散型台帳を目指しています。そのためには、Cordaソフトウェアを使用する多くのソリューションが、一連の共通の標準と基準に準拠している必要があります。これらの基準のいくつかは、しばしば最終状態の原則として知られ、次のとおりです。
CorDappは、Corda分散アプリケーションの省略形です。CorDappsは、Cordaノードで実行される分散アプリケーションです。以下は、CorDappの主要コンポーネントです。
状態はデータで構成されています。これらはトランザクション間のデータを追跡し、不変です。つまり、形成された後に変更することはできません。代わりに、変更を加えると、新しい継承状態が作成される必要があります。
コントラクトは、トランザクションの入力と出力に適用される検証基準を定義します。コントラクトは、トランザクションの入力状態と出力状態が有効であり、無効なトランザクションが回避されることを保証します。1つ以上のコントラクトがCorDappに存在する場合があり、各コントラクトは1つ以上の状態のルールを提供します。
フローは、CorDappがネットワーク上で実行する可能性のあるアクティビティであり、CorDappのビジネスロジックを構成します。フローにより、パーティは中央コントローラを使用せずに操作を調整できます。
トランザクションは、元帳の更新要求です。現在の入力状態を消費し、新しい状態を出力して元帳を更新します。トランザクションがノードによって受け入れられる前に、トランザクションは一意で有効であり、適切な関係者によって署名されている必要があります。
公証人は、ネットワーク資産の重複した支出を防ぐのに役立つCordaネットワークサービスです。これは、各トランザクションに、前のトランザクションで使用されていない一意の入力状態のみが含まれることを保証することによって行われます。公証人も取引の最終性を与えます。公証人が署名した後、取引は完了したと見なされます。
Cordaでは、有効かつ一意のトランザクションを証明することでコンセンサスを確立できます。コンセンサスは、ノードがネットワークの現在の状態について合意できるようにする方法です。提案された取引を元帳に入力する前に、両当事者はそれが合法であることに同意する必要があります。
Cordaブロックチェーンでのトークンの発行をモデル化するCorDappを作成します。CorDappは、トークンの発行者、所有者、および発行された金額を追跡します。
CorDapp開発に必要なソフトウェアは4つあります。
CorDappを設定するには、まず、GitHubリポジトリからCordaJavaテンプレートのクローンを作成します。cordapp-template-java
任意のIDEで開きます。IntelliJIDEを使用します。
繰り返しになりますが、状態は不変であり、トランザクション間のデータを追跡します。CorDappには、、、、などの状態に保存する一連の属性がissuer
ありholder
ますamount
。
/contracts/src/main/java/com/template/states
次の名前の新しいJavaクラスに移動して作成しますTokenState
。
package com.template.states
import com.template.contracts.TokenContract;
import net.corda.core.identity.AbstractParty;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.Party;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
@BelongsToContract(TokenContract.class)
public class TokenState implements ContractState {
private Party issuer;
private Party holder;
private int amount;
public TokenState(Party issuer, Party holder, int amount){
this.issuer = issuer;
this.holder = holder;
this.amount = amount;
}
public Party getHolder() {
return holder;
}
public Party getIssuer() {
return issuer;
}
public int getAmount() {
return amount;
}
@NotNull
@Override
public List<AbstractParty> getParticipants() {
return Arrays.asList(issuer, holder);
}
}
上記のコードでは、クラスTokenState
から継承するというクラスを作成しますContractState
。ContractState
クラスは、状態を実装していることをコーダに伝えます。
@BelongsToContract
次に、状態と契約の関係を確立するアノテーションを追加します。これがないと、州はそれを検証するためにどの契約が使用されているかを知りません。このアノテーションを追加すると、まだ作成されていないため、IntelliJでエラーが発生しますTokenContract
。
次に、、、、の3つの属性を作成issuer
しholder
ますamount
。issuer
とholder
属性はどちらもノード上のエンティティを表すため、タイプが与えられますParty
。
次に、属性ごとに3つのgetterメソッドを作成します。最後に、getParticipants
どの当事者がトランザクションを認識すべきかを定義するメソッドを作成します。この場合、とだけがトランザクションを認識できるようにしますissuer
。holder
繰り返しになりますが、契約は州がどのように進化できるかのルールを定義します。トランザクションが正常に完了する前に、特定の検証を行います。したがって、各州は契約にリンクされています。
/contracts/src/main/java/com/template/contracts
次の名前の新しいJavaクラスに移動して作成しますTokenContract
。
package com.template.contracts
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
import net.corda.core.transactions.LedgerTransaction;
import org.jetbrains.annotations.NotNull;
import com.template.states.TokenState;
public class TokenContract implements Contract {
public static final String ID = "contracts.TokenContract";
@Override
public void verify(@NotNull LedgerTransaction tx) {
if(tx.getCommands().size() != 1) {
throw new IllegalArgumentException("expects only one command: ISSUE");
}
if(tx.getCommand(0).getValue() instanceof Commands.Issue){
throw new IllegalArgumentException("issue command expected");
}
TokenState state = (TokenState) tx.getOutput(0);
int amountIssued = state.getAmount();
if (amountIssued <= 0){
throw new IllegalArgumentException("amount must be greater than zero");
}
if(! (tx.getCommand(0).getSigners().contains(state.getIssuer().getOwningKey()))){
throw new IllegalArgumentException("transaction must be signed by issuer");
}
}
// Used to indicate the transaction's intent.
public interface Commands extends CommandData {
class Issue implements Commands {}
}
}
上記のコードでは、クラスTokenContract
から継承するというクラスを作成しますContract
。クラスは、Contract
私たちが契約を履行していることをコーダに伝えます。
まず、ID
テスト環境でトランザクションを構築するときにコントラクトを識別するという属性を作成します。このID
属性は完全にオプションです。
Contract
継承したクラスによって与えられたメソッドの1つはverify
メソッドであり、これをオーバーライドする必要があります。このverify
メソッドは、トランザクションを入力として受け取り、定義されたルールに対してそれらを評価します。verify
メソッドが例外をスローしない場合、トランザクションは有効です。
上記のコードを使用して、コントラクトは次のチェックを実行します。
issue
使用可能最後に、トークンを別のパーティに発行する予定なので、クラスIssue
から継承するというクラスを作成しますCommand
。このCommand
クラスは、実行されているアクションのタイプを示すために使用されます。
繰り返しになりますが、フローにはCorDappのビジネスロジックが含まれています。イニシエーターフローは、トランザクションを開始するノードによって実行されます。これはissuer
、この場合です。
workflows/src/main/java/com/template/flows
次の名前の新しいJavaクラスに移動して作成しますFlowInitiator
。
package com.template.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.bootcamp.contracts.TokenContract;
import com.bootcamp.states.TokenState;
import net.corda.core.flows.*;
import net.corda.core.identity.CordaX500Name;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
import net.corda.core.contracts.CommandData;
import static java.util.Collections.singletonList;
@InitiatingFlow
@StartableByRPC
public static class TokenFlowInitiator extends FlowLogic<SignedTransaction> {
private final Party owner;
private final int amount;
public TokenFlowInitiator(Party owner, int amount) {
this.owner = owner;
this.amount = amount;
}
private final ProgressTracker progressTracker = new ProgressTracker();
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
/** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
// We get a reference to our own identity.
Party issuer = getOurIdentity();
/* ============================================================================
* TODO 1 - Create our TokenState to represent on-ledger tokens!
* ===========================================================================*/
// We create our new TokenState.
TokenState tokenState = new TokenState(issuer, owner, amount);
/* ============================================================================
* TODO 3 - Build our token issuance transaction to update the ledger!
* ===========================================================================*/
// We build our transaction.
TransactionBuilder transactionBuilder = new TransactionBuilder.setNotary(notary).addOutputState(tokenState).addCommand(new TokenContract.Commands.Issue(), Arrays.asList(issuer.getOwningKey(), owner.getOwningKey()));
/* ============================================================================
* TODO 2 - Write our TokenContract to control token issuance!
* ===========================================================================*/
// We check our transaction is valid based on its contracts.
transactionBuilder.verify(getServiceHub());
FlowSession session = initiateFlow(owner);
// We sign the transaction with our private key, making it immutable.
SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
// The counterparty signs the transaction
SignedTransaction fullySignedTransaction = subFlow(new CollectSignaturesFlow(signedTransaction, singletonList(session)));
// We get the transaction notarised and recorded automatically by the platform.
return subFlow(new FinalityFlow(fullySignedTransaction, singletonList(session)));
}
}
上記のコードでは、クラスTokenFlowInitiator
から継承するというクラスを作成しますFlowLogic
。FlowLogic
クラスは、フローを作成していることをコーダに伝えます。
次に、2つの注釈とを追加@InitiatingFlow
し@StartableByRPC
ます。注釈は、この@InitiatingFlow
フローが開始フローであることを示しています。一方、@StartableByRPC
注釈により、RPCはフローを開始できます。
progressTracker
次に、フローの各ステージをチェックポイントし、コードで各チェックポイントに到達したときに指定されたメッセージを出力するという変数を作成します。
次に、call
フローの開始時にCordaが呼び出すメソッドを作成します。メソッド内ではcall
、最初に公証人を作成し、それを。という変数に格納しますnotary
。私たちは複数の当事者を扱っているので、当事者間の合意に達するために公証人のサービスが必要です。
IDを取得し、それを。という変数に格納しますissuer
。次に、の新しいインスタンスを作成してトークンを作成し、、、、およびを引数としてTokenState
渡します。issuerowneramount
次に、の新しいインスタンスを作成してトランザクション提案を作成しますTransactionBuilder
。公証人を設定し、コマンドを追加し、トランザクションに署名するために、さまざまなメソッドをチェーンします。
最後に、メソッドFlowSession
を使用してカウンターパーティから開始します。InitiateFlow
このプロセスにより、状態をカウンターパーティに送信できます。CollectSignaturesFlow
次に、サブフローを呼び出して署名を収集します。
レスポンダーフローは、カウンターパーティによって実行されます。トランザクションを受信して記録し、トランザクションが成功した場合は確認応答を返送することで発行者のフローに応答します。
workflows/src/main/java/com/template/flows
次の名前の新しいJavaクラスに移動して作成しますTokenFlowResponder
。
package com.template.flows;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.flows.*;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
@InitiatedBy(TokenFlowInitiator.class)
public static class TokenFlowResponder extends FlowLogic<Void>{
//private variable
private FlowSession counterpartySession;
//Constructor
public TokenFlowResponder(FlowSession counterpartySession) {
this.counterpartySession = counterpartySession;
}
@Suspendable
@Override
public Void call() throws FlowException {
SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {});
//Stored the transaction into data base.
subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
return null;
}
}
上記のコードでは、クラスTokenFlowResponder
から継承するというクラスを作成しますFlowLogic
。@InitiatedBy
次に、アノテーションを追加し、TokenFlowInitiator
クラスを引数として渡して、フローを開始したコーダに通知します。
次に、トランザクションとフローイニシエーターから受け取った署名を検証するcall
メソッドを作成します。オプションで、従来、安全のために一連のテストを実行するためにsubFlow
呼び出される新しいメソッドを作成できます。checkTransaction
CorDappを開始するには、最初にプロジェクトのルートに移動し、次のコマンドを実行して、CorDappをデプロイする必要があります。
#Mac or Linux
./gradlew clean deployNodes
#Windows
gradlew.bat clean deployNodes
CorDappが正常にビルドされると、CorDappがインストールされた3つのノードが生成されます。これらはbuild/nodes
フォルダにあります。
ノードとCorDappを起動するには、ルートディレクトリから次のコマンドを実行します。
#Mac or Linux
./build/nodes/runnodes
#Windows
.\build\nodes\runnodes.bat
上記のコードは、ノードごとに新しいターミナルウィンドウを開始します。各ターミナルの起動に少し時間がかかります。ノードの準備が整うと、ターミナルにウェルカムメッセージが表示されます。
CorDappが正常に機能したかどうかを確認するには、次のコマンドを実行してフローを開始します。
flow start TokenFlowInitiator owner: PartyB, amount: 100
成功すると、確認メッセージが表示されます。
ブロックチェーンは画期的なテクノロジーであり、プライベートブロックチェーンを使用するシステムのおかげで、規制対象の企業はこの変更から除外されません。Cordaのようなブロックチェーンプロジェクトは、データをプライベートに保ちながら、企業に必要な柔軟性を提供します。この記事では、Cordaをじっと見つめ、CorDappsの作成方法を学びました。
このチュートリアルを楽しんでいただければ幸いです。ご不明な点がございましたら、お気軽にコメントを残してください。
1651673160
El lanzamiento de bitcoin el 3 de enero de 2009 puso en marcha tendencias como los activos digitales y las monedas digitales y, desde entonces, se han creado más cadenas de bloques como Ethereum y Solana. A pesar de tener diferentes características y casos de uso, estas cadenas de bloques tienen una cosa en común; fueron diseñados para operar democráticamente sin reguladores. Por lo tanto, este modelo no es adecuado para industrias reguladas, en las que los datos deben mantenerse confidenciales y compartirse entre partes de confianza. Por esta razón, existen cadenas de bloques privadas.
Una cadena de bloques privada es una cadena de bloques autorizada. Una cadena de bloques privada contiene entidades llamadas operadores de red que controlan la red y pueden configurar permisos y controles de acceso de los otros nodos. Para mantener la privacidad y la confianza, solo las entidades que participan en una transacción tendrán conocimiento de ella, mientras que otras no podrán acceder a ella.
Algunos ejemplos de plataformas digitales que utilizan cadenas de bloques privadas incluyen Hyperledger Fabric , Ripple y R3's Corda . En este artículo, exploraremos Corda y aprenderemos a crear CorDapps. ¡Empecemos!
Corda es una tecnología de registro distribuido (DLT) peer-to-peer (P2P) autorizada que facilita el desarrollo de aplicaciones en mercados regulados. Con Corda, las partes pueden descubrirse libremente y realizar transacciones entre sí en una sola red abierta mientras confían en la identificación de los participantes de la red.
A la larga, Corda aspira a ser un libro mayor distribuido mundialmente compartido. Para ello, las numerosas soluciones que utilizan el software de Corda deben cumplir un conjunto de estándares y criterios comunes. Algunos de estos criterios, a menudo conocidos como principios de estado final, son los siguientes:
CorDapp es una abreviatura de aplicación distribuida de Corda. CorDapps son aplicaciones distribuidas que se ejecutan en el nodo de Corda. Los siguientes son los componentes clave de una CorDapp:
Los estados están hechos de datos. Realizan un seguimiento de los datos entre transacciones y son inmutables, lo que significa que no se pueden cambiar una vez que se han formado. En cambio, cualquier modificación debe dar como resultado la creación de un nuevo estado sucesor.
Los contratos definen los criterios de validación que se aplicarán a las entradas y salidas de transacciones. Los contratos garantizan que los estados de entrada y salida de la transacción son válidos y que se evitan las transacciones no válidas. Pueden existir uno o más contratos en una CorDapp, cada uno de los cuales proporciona reglas para uno o más estados.
Los flujos son las actividades que su CorDapp puede realizar en una red y constituyen la lógica comercial de su CorDapp. Los flujos permiten a las partes coordinar sus operaciones sin el uso de un controlador central.
Una transacción es una solicitud de actualización del libro mayor. Consume los estados de entrada actuales y genera otros nuevos para actualizar el libro mayor. Antes de que los nodos acepten una transacción, esta debe ser única, válida y estar firmada por las partes correspondientes.
Un notario es un servicio de la red de Corda que ayuda a evitar el gasto duplicado de los activos de la red. Lo hace garantizando que cada transacción solo incluya estados de entrada únicos que no hayan sido utilizados por una transacción anterior. Un notario también da una finalidad de transacción. Una transacción se considera finalizada después de que haya sido firmada por el notario.
En Corda, puede establecer un consenso probando una transacción que sea válida y única. El consenso es un método que permite a los nodos ponerse de acuerdo sobre el estado actual de la red. Antes de que una transacción propuesta pueda ingresarse en el libro mayor, ambas partes deben estar de acuerdo en que es legal.
Crearemos una CorDapp para modelar la emisión de tokens en la cadena de bloques de Corda. Nuestro CorDapp hará un seguimiento del emisor del token, el titular y la cantidad que se emite.
Hay cuatro piezas de software necesarias para el desarrollo de CorDapp:
Para configurar nuestra CorDapp, primero, clone la plantilla Corda Java de su repositorio de GitHub. Abra cordapp-template-java
en cualquier IDE de su elección. Usaré IntelliJ IDE.
Para reiterar, los estados son inmutables y realizan un seguimiento de los datos entre transacciones. Nuestra CorDapp tendrá un conjunto de atributos que almacenaremos en nuestro estado, como issuer
, holder
y amount
.
Navegue /contracts/src/main/java/com/template/states
y cree una nueva clase de Java llamada TokenState
:
package com.template.states
import com.template.contracts.TokenContract;
import net.corda.core.identity.AbstractParty;
import net.corda.core.contracts.BelongsToContract;
import net.corda.core.contracts.ContractState;
import net.corda.core.identity.Party;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
@BelongsToContract(TokenContract.class)
public class TokenState implements ContractState {
private Party issuer;
private Party holder;
private int amount;
public TokenState(Party issuer, Party holder, int amount){
this.issuer = issuer;
this.holder = holder;
this.amount = amount;
}
public Party getHolder() {
return holder;
}
public Party getIssuer() {
return issuer;
}
public int getAmount() {
return amount;
}
@NotNull
@Override
public List<AbstractParty> getParticipants() {
return Arrays.asList(issuer, holder);
}
}
En el código anterior, creamos una clase llamada TokenState
que hereda de la ContractState
clase. La ContractState
clase le dice a Corda que estamos implementando un estado.
A continuación, añadimos la @BelongsToContract
anotación, que establece la relación entre un estado y un contrato. Sin esto, su estado no sabe qué contrato se utiliza para verificarlo. Agregar esta anotación desencadena un error en IntelliJ porque aún tenemos que crear nuestro archivo TokenContract
.
Luego, creamos tres atributos, issuer
, holder
y amount
. Los atributos issuer
y holder
reciben un tipo de Party
porque ambos representan entidades en el nodo.
A continuación, creamos tres métodos captadores para cada uno de los atributos. Finalmente, creamos un getParticipants
método que define qué partes deben estar al tanto de la transacción. En nuestro caso, solo queremos que el issuer
y el holder
sean conscientes de la transacción.
Para reiterar, los contratos definen las reglas de cómo los estados pueden evolucionar. Realizan ciertas validaciones antes de que una transacción se realice con éxito. Por lo tanto, cada estado está vinculado a un contrato.
Navegue /contracts/src/main/java/com/template/contracts
y cree una nueva clase de Java llamada TokenContract
:
package com.template.contracts
import net.corda.core.contracts.CommandData;
import net.corda.core.contracts.Contract;
import net.corda.core.transactions.LedgerTransaction;
import org.jetbrains.annotations.NotNull;
import com.template.states.TokenState;
public class TokenContract implements Contract {
public static final String ID = "contracts.TokenContract";
@Override
public void verify(@NotNull LedgerTransaction tx) {
if(tx.getCommands().size() != 1) {
throw new IllegalArgumentException("expects only one command: ISSUE");
}
if(tx.getCommand(0).getValue() instanceof Commands.Issue){
throw new IllegalArgumentException("issue command expected");
}
TokenState state = (TokenState) tx.getOutput(0);
int amountIssued = state.getAmount();
if (amountIssued <= 0){
throw new IllegalArgumentException("amount must be greater than zero");
}
if(! (tx.getCommand(0).getSigners().contains(state.getIssuer().getOwningKey()))){
throw new IllegalArgumentException("transaction must be signed by issuer");
}
}
// Used to indicate the transaction's intent.
public interface Commands extends CommandData {
class Issue implements Commands {}
}
}
En el código anterior, creamos una clase llamada TokenContract
que hereda de la Contract
clase. La Contract
clase le dice a Corda que estamos implementando un contrato.
Primero, creamos un atributo llamado ID
que identificará nuestro contrato al construir nuestra transacción en entornos de prueba. El ID
atributo es puramente opcional.
Uno de los métodos que nos da la Contract
clase que heredamos es el verify
método, que debemos anular. El verify
método toma transacciones como entrada y las evalúa contra reglas definidas. Una transacción es válida si el verify
método no arroja una excepción.
Con el código anterior, nuestro contrato realiza las siguientes comprobaciones:
issue
se puede usar el comandoFinalmente, dado que tenemos la intención de emitir el token a otra parte, creamos una clase llamada Issue
que hereda de la Command
clase. La Command
clase se utiliza para indicar el tipo de acción que se está realizando.
Para reiterar, los flujos contienen la lógica comercial de nuestra CorDapp. El flujo del iniciador lo ejecuta el nodo que inicia la transacción, que sería issuer
en nuestro caso.
Navegue workflows/src/main/java/com/template/flows
y cree una nueva clase de Java llamada FlowInitiator
:
package com.template.flows;
import co.paralleluniverse.fibers.Suspendable;
import com.bootcamp.contracts.TokenContract;
import com.bootcamp.states.TokenState;
import net.corda.core.flows.*;
import net.corda.core.identity.CordaX500Name;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
import net.corda.core.contracts.CommandData;
import static java.util.Collections.singletonList;
@InitiatingFlow
@StartableByRPC
public static class TokenFlowInitiator extends FlowLogic<SignedTransaction> {
private final Party owner;
private final int amount;
public TokenFlowInitiator(Party owner, int amount) {
this.owner = owner;
this.amount = amount;
}
private final ProgressTracker progressTracker = new ProgressTracker();
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
/** Explicit selection of notary by CordaX500Name - argument can by coded in flows or parsed from config (Preferred)*/
final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
// We get a reference to our own identity.
Party issuer = getOurIdentity();
/* ============================================================================
* TODO 1 - Create our TokenState to represent on-ledger tokens!
* ===========================================================================*/
// We create our new TokenState.
TokenState tokenState = new TokenState(issuer, owner, amount);
/* ============================================================================
* TODO 3 - Build our token issuance transaction to update the ledger!
* ===========================================================================*/
// We build our transaction.
TransactionBuilder transactionBuilder = new TransactionBuilder.setNotary(notary).addOutputState(tokenState).addCommand(new TokenContract.Commands.Issue(), Arrays.asList(issuer.getOwningKey(), owner.getOwningKey()));
/* ============================================================================
* TODO 2 - Write our TokenContract to control token issuance!
* ===========================================================================*/
// We check our transaction is valid based on its contracts.
transactionBuilder.verify(getServiceHub());
FlowSession session = initiateFlow(owner);
// We sign the transaction with our private key, making it immutable.
SignedTransaction signedTransaction = getServiceHub().signInitialTransaction(transactionBuilder);
// The counterparty signs the transaction
SignedTransaction fullySignedTransaction = subFlow(new CollectSignaturesFlow(signedTransaction, singletonList(session)));
// We get the transaction notarised and recorded automatically by the platform.
return subFlow(new FinalityFlow(fullySignedTransaction, singletonList(session)));
}
}
En el código anterior, creamos una clase llamada TokenFlowInitiator
que hereda de la FlowLogic
clase. La FlowLogic
clase le dice a Corda que estamos creando un Flujo.
Luego, agregamos dos anotaciones, @InitiatingFlow
y @StartableByRPC
. La @InitiatingFlow
anotación indica que este flujo es el flujo iniciador. Por otro lado, la @StartableByRPC
anotación permite que RPC inicie el flujo.
A continuación, creamos una variable llamada progressTracker
que marca puntos de control en cada etapa del flujo y genera los mensajes especificados cuando se alcanza cada punto de control en el código.
A continuación, creamos el call
método, al que llama Corda cuando se inicia el flujo. Dentro del call
método, primero creamos un notario y lo almacenamos en una variable llamada notary
. Dado que estamos tratando con múltiples partes, necesitamos un servicio de notario para llegar a un consenso entre las partes.
Obtenemos nuestra identidad y la almacenamos en una variable llamada issuer
. A continuación, creamos nuestro token creando una nueva instancia de TokenState
y pasando los argumentos issuer
, owner
y .amount
Luego, construimos nuestra propuesta de transacción creando una nueva instancia de TransactionBuilder
. Encadenamos diferentes métodos para configurar nuestro notario, agregar comandos y firmar la transacción.
Finalmente, comenzamos FlowSession
con la contraparte utilizando el InitiateFlow
método. Este proceso nos permite enviar el estado a la contraparte. Luego llamamos al CollectSignaturesFlow
subflujo para recopilar firmas.
El flujo de respuesta lo ejecuta la contraparte. Recibe y registra la transacción, luego responde al flujo del emisor enviando un acuse de recibo si la transacción fue exitosa.
Navegue workflows/src/main/java/com/template/flows
y cree una nueva clase de Java llamada TokenFlowResponder
:
package com.template.flows;
import co.paralleluniverse.fibers.Suspendable;
import net.corda.core.flows.*;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
@InitiatedBy(TokenFlowInitiator.class)
public static class TokenFlowResponder extends FlowLogic<Void>{
//private variable
private FlowSession counterpartySession;
//Constructor
public TokenFlowResponder(FlowSession counterpartySession) {
this.counterpartySession = counterpartySession;
}
@Suspendable
@Override
public Void call() throws FlowException {
SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(counterpartySession) {});
//Stored the transaction into data base.
subFlow(new ReceiveFinalityFlow(counterpartySession, signedTransaction.getId()));
return null;
}
}
En el código anterior, creamos una clase llamada TokenFlowResponder
que hereda de la FlowLogic
clase. Luego agregamos la @InitiatedBy
anotación y pasamos la TokenFlowInitiator
clase como argumento, diciéndole a Corda quién inició el flujo.
Luego, creamos el call
método con un subFlow
que verificará la transacción y las firmas que recibió del iniciador del flujo. Opcionalmente, podemos crear convencionalmente un nuevo método llamado checkTransaction
para realizar una serie de pruebas solo para estar seguros.
Para iniciar nuestra CorDapp, primero debemos implementarla navegando a la raíz de nuestro proyecto y ejecutando los siguientes comandos:
#Mac or Linux
./gradlew clean deployNodes
#Windows
gradlew.bat clean deployNodes
Si nuestra CorDapp se construye con éxito, genera tres nodos con la CorDapp instalada en ellos. Estos se pueden encontrar en la build/nodes
carpeta.
Para iniciar los nodos y nuestra CorDapp, ejecute el siguiente comando desde nuestro directorio raíz:
#Mac or Linux
./build/nodes/runnodes
#Windows
.\build\nodes\runnodes.bat
El código anterior iniciará una nueva ventana de terminal para cada nodo. Dé a cada terminal algo de tiempo para comenzar y recibirá un mensaje de bienvenida en el terminal una vez que el nodo esté listo.
Para verificar si nuestro CorDapp funcionó correctamente, podemos intentar iniciar un flujo ejecutando el siguiente comando:
flow start TokenFlowInitiator owner: PartyB, amount: 100
Si tiene éxito, recibirá un mensaje de confirmación.
La cadena de bloques es una tecnología que cambia las reglas del juego, y las empresas reguladas no se quedan fuera de este cambio gracias a los sistemas que utilizan cadenas de bloques privadas. Los proyectos de cadena de bloques como Corda brindan a las empresas la flexibilidad que necesitan y, al mismo tiempo, mantienen la privacidad de los datos. En este artículo, exploramos cómo empezar con Corda, aprendiendo cómo hacer CorDapps.
Espero que hayas disfrutado este tutorial, y no dudes en dejar un comentario si tienes alguna pregunta.
Fuente: https://blog.logrocket.com/how-to-write-dapps-corda/