# Di chuyển từ các phiên bản trước đó của Marlowe

Hướng dẫn này giải thích phiên bản mới nhất của Marlowe khác với các phiên bản ngôn ngữ trước đó như thế nào.

### Bỏ `Both`

Chúng tôi không bao gồm một cấu trúc `Both` trong phiên bản Marlowe mới nhất, cấu trúc này làm cho tất cả các hợp đồng có trình tự.

Vì không có phiên bản nào của Marlowe có giao tiếp giữa các chi nhánh của `Both`nên chức năng bổ sung duy nhất được cung cấp `Both`trên thực tế là khả năng đợi nhiều khoản tiền gửi cùng một lúc.

Chúng tôi cải thiện chức năng này bằng cách cập nhật  cấu trúc `When`. Thay vì để các nhánh khác nhau chờ các đầu vào khác nhau, chúng ta chuyển sang một mô hình hoàn toàn tuần tự và đồng bộ, nơi chúng ta có thể chờ một trong một số đầu vào có thể cùng một lúc (như trong `select`).

Lý do chúng tôi loại bỏ cấu trúc này là các chương trình tuần tự dễ phân tích hơn và dễ lý luận hơn, vì không cần đồng bộ hóa và không có cơ hội cho các race conditions.

### Bao gồm các tài khoản

Trong các phiên bản Marlowe trước đó, mỗi cam kết có thời gian chờ riêng. Điều này có nghĩa là tiền được ký gửi trong một hợp đồng *không thể thay thế được* , bởi vì nó có thể được phân biệt bằng thời gian chờ của nó. Để đạt được khả năng thay thế, chúng tôi đã loại bỏ thời gian chờ khỏi các cấu trúc riêng lẻ và có một thời gian chờ duy nhất cho tất cả các cam kết. Thời *hạn hợp đồng* này có thể suy ra đơn giản từ thời gian chờ trong hợp đồng.

Tuy nhiên, chúng tôi bao gồm *các tài khoản (accounts)* để tổ chức số tiền được gửi vào hợp đồng. Điều này giúp minh bạch hơn cách tiền luân chuyển trong hợp đồng và đặc biệt xác định tiền sẽ được *hoàn trả (refunded)* cho ai khi hợp đồng chấm dứt.

Mỗi tài khoản được xác định bởi một người tham gia; người tham gia cho biết ai sẽ nhận được tiền trong tài khoản theo mặc định khi `Close`đạt được.

Lý do chúng tôi chọn bao gồm các tài khoản là vì không có chúng, chúng tôi nhận thấy rằng về cơ bản chúng tôi đang theo dõi các tài khoản theo cách thủ công. Ngoài ra, trong mỗi lá của AST, chúng tôi thấy mình phải tính toán xem chúng tôi phải trả lại bao nhiêu cho mỗi người tham gia, làm lộn xộn cái cây với “boilerplate” lặp đi lặp lại. Do đó, việc tổ chức tiền trong tài khoản có thể làm cho các hợp đồng dễ dàng lập luận hơn và ít bị sai sót hơn.

Lưu ý rằng chúng tôi có thể cung cấp đầy đủ khả năng thay thế bằng cách sử dụng một tài khoản. Chúng ta chỉ cần viết các `Pay`lệnh thích hợp trong các lá của hợp đồng. Nếu tất cả tiền được trả cho người tham gia, thì `Close`không có hiệu lực. [1](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id5)

#### Thảo luận: Tài khoản ẩn và tài khoản rõ ràng

Nhiều trường hợp sử dụng cho tài khoản - và tất cả những trường hợp mà chúng tôi có thể xác định cho hợp đồng ACTUS - có một tài khoản cho mỗi người tham gia và một người tham gia cho mỗi tài khoản (“mô hình 1-1”). Điều này đặt ra câu hỏi liệu chúng ta có nên xử lý ngầm các tài khoản hay không, với mỗi người tham gia sở hữu một tài khoản.

Mặt khác, có nhiều tình huống hợp lý cho các tài khoản không tuân theo mô hình 1-1.

Ví dụ khi nhiều người tham gia sử dụng một tài khoản.

* Alice sở hữu một tài khoản mà cô ấy cam kết chi tiền cho Bob (hãy nghĩ Alice là chủ của Bob). Bob có thể chi tiêu đến giới hạn trong tài khoản, nhưng sau khi hết thời gian cam kết, Alice sẽ thu hồi bất cứ thứ gì còn lại.
* Alice sở hữu một tài khoản mà cô ấy cam kết chi tiền cho Bob và Carol (hãy nghĩ Alice là chủ của Bob và Carol). Họ có thể chi tiêu (cùng nhau) đến giới hạn trong tài khoản, nhưng sau khi hết thời gian cam kết, Alice thu hồi bất cứ thứ gì còn lại.
* Mặt khác, mỗi người có thể được cấp một tài khoản riêng để chi tiêu: điều đó sẽ thực thi các giới hạn riêng lẻ cũng như giới hạn tổng hợp.
* Nếu Bob \[và Carol] muốn tiêu tiền, họ cũng có thể thêm tiền vào tài khoản, nhưng họ nên nhận ra rằng bất cứ thứ gì không sử dụng sẽ được hoàn lại cho Alice.

Ví dụ về nhiều tài khoản cho một người:

* Ví dụ về bảo lãnh phát hành sẽ phù hợp ở đây. Một người chấp nhận rủi ro cấp độ một và rủi ro cấp độ thứ hai bằng cách sử dụng các tài khoản khác nhau. Chỉ khi bảo lãnh phát hành cấp một của tất cả những người tham gia được chi tiêu thì chi tiêu cấp hai mới xảy ra.

### `Close`thay thế `Null`/`Pay`

Vì tất cả các hợp đồng bây giờ là tuần tự, chúng ta có thể dễ dàng biết khi nào một hợp đồng chấm dứt, tức là: khi nào thì chỉ `Null`còn lại. Chúng tôi sử dụng cơ hội này để *đóng* hợp đồng và hoàn trả bất kỳ khoản tiền nào còn lại trong tài khoản; vì lý do này, chúng tôi đã đổi tên thành `Null` thành`Close` (giúp dễ hiểu).

Như đã lưu ý trước đó, không còn thời gian chờ rõ ràng nào trong các tài khoản nữa, vì tất cả các hợp đồng cuối cùng sẽ giảm xuống `Close`. Trên thực tế, chúng ta có thể tính toán giới hạn trên một cách tĩnh và hiệu quả cho thời điểm điều này xảy ra, làm cho khía cạnh này của Marlowe có thể phân tích được.

### Pay

`Pay`bây giờ là ngay lập tức và nó có một phần tiếp theo và ít tham số hơn. [2](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id6) Nó cho phép thanh toán từ một tài khoản cho một người tham gia hoặc đến một tài khoản khác. Chúng tôi đã loại bỏ `PayAll`, vì nó có thể được mô phỏng dưới dạng một chuỗi hữu hạn `Pay`. Trên thực tế, chúng ta có thể định nghĩa `payAll`như một hàm Haskell (xem `zeroCouponBond`ví dụ).

Đó là hệ quả của việc loại bỏ `Both`cấu trúc, đó là bây giờ nó không rõ ràng mà `Pay`đi trước: tất cả chúng đều tuần tự, do đó hỗ trợ phân tích. Với `Both`cấu trúc, chúng tôi có thể có khả năng `Pays`xảy ra theo bất kỳ thứ tự nào (vì cả hai bên của `Both`được cho là chạy đồng thời).

### Multi-clause When

Chúng tôi đã sửa đổi `When`để bao gồm một tập hợp các hành động khả thi có thể được nhập vào trong khi `When`chờ đợi. Chúng tôi gọi cách tiếp cận này là “Một trong nhiều”, bởi vì nó chấp nhận một hành động trong số nhiều hành động được phép tiềm năng. `When`vẫn như sau:

```
When [Case] Timeout Contract
```

`When`sẽ đợi `Timeout`và tiếp tục ở đâu `Contract`, hoặc tiếp tục như được chỉ định trong một trong các `Cases`điều kiện nào xảy ra trước. `Case`được định nghĩa là:

```
data Case = Case Action Contract
```

và `Action`như:

```
data Action = Deposit Party Party Token Value
            | Choice ChoiceId [Bound]
            | Notify Observation
```

Một `Case`mệnh đề sẽ chỉ được kích hoạt nếu điều tương ứng `Action` được tạo ra và nó sẽ tiếp tục như vậy `Contract`. Trong trường hợp có hai `Actions`kết quả khớp, cái đầu tiên trong danh sách sẽ được thực thi.

Ba loại hành động được hỗ trợ:

* `Deposit`đại diện cho một khoản tiền gửi vào tài khoản; cái này ban đầu được gọi `Commit`.
* `Choice`đại diện cho sự lựa chọn được thực hiện bởi một người tham gia từ bên trong một tập hợp các `Integer`giá trị (được chỉ định bởi danh sách `Bounds`).
* `Notify`sẽ đợi một `Notify`hành động được đưa ra khi `Observation`đúng. Chúng tôi gọi nó là `Notify`để làm rõ rằng chúng tôi không thể chỉ chờ đợi `Observations`mà phải có ai đó kích hoạt hợp đồng trong một thời điểm khi giá trị `Observation`là sự thật.

Chúng tôi đã loại bỏ việc bổ sung các quan sát vào `Deposit`và `Choice` vì sẽ không rõ ràng liệu `Observation`sẽ được đánh giá trước hay sau khi áp dụng hành động.

Ngoài các trường hợp rõ ràng trong `When`, chúng ta phải nhớ rằng nhánh *thời gian chờ* cũng là một trường hợp và nó cũng cần được kích hoạt (tương tự như `Notify`). [3 ](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id7)[4](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id8)

### Quan sát và Giá trị

Chúng tôi đã loại bỏ `Observations`và `Values`điều đó có thể được thể hiện bằng cách kết hợp những thứ khác: như chung `AvailableMoney`(cho toàn bộ hợp đồng) hoặc tương tự `DepositedMoneyBy`, ghi nhớ số tiền mà người tham gia đã ký gửi, vì hợp đồng có thể được cấu trúc lại để tuân theo điều đó và hỗ trợ sẽ yêu cầu thông tin bổ sung trong trạng thái (tính đơn giản).

Chúng tôi đã giữ lại `ChoseSomething`quan sát, mặc dù, trong ngữ nghĩa được đề xuất, mọi sự xuất hiện của `ChoseSomething`có thể được đánh giá tĩnh và hiệu quả bằng cách kiểm tra ngữ cảnh của nó.

Ví dụ: trong hợp đồng sau, chúng ta có thể thấy rằng lần xuất hiện đầu tiên của `ChoseSomething`sẽ đánh giá `True`và lần xuất hiện thứ hai là `False`:

```
When [ Case (Choice (ChoiceId 1 Alice) [(1,1)])
            (If (ChoseSomething (ChoiceId 1 Alice))
                Close
                Close)
     , Case (Choice (ChoiceId 2 Bob) [(2,2)])
            (If (ChoseSomething (ChoiceId 1 Alice))
                Close
                Close)]
     0
     Close
```

Tuy nhiên, chúng tôi đã chọn giữ nguyên cấu trúc vì hai lý do:

* Nó cho phép mã tái sử dụng (tiện lợi). Ví dụ, trong hợp đồng trước, chúng ta có thể xác định `chosen1`:

```
let chosen1 = If (ChoseSomething (ChoiceId 1 1))
                 Close
                 Close
in
When [ Case (Choice (ChoiceId 1 1) [(1,1)])
            chosen1
     , Case (Choice (ChoiceId 2 2) [(2,2)])
            chosen1]
     0
     Close
```

Nhưng điều này sẽ không thể thực hiện được nếu chúng ta không có cấu trúc `ChoseSomething`, vì giá trị mà nó giảm phụ thuộc vào ngữ cảnh.

* Có thể không còn xảy ra trường hợp các lần xuất hiện của cấu trúc có thể được đánh giá tĩnh nếu chúng ta mở rộng `When`cấu trúc để hỗ trợ “nhiều trong số nhiều” đầu vào.

### Bao gồm các khoảng thời gian

Đặc tả EUTxO cung cấp các tập lệnh xác thực với khoảng thời gian thay vì với số vị trí. Điều này là để thúc đẩy thuyết xác định trong các tập lệnh xác thực. Tuy nhiên, chúng tôi đã giữ thời gian chờ của `When` (thời gian chờ duy nhất) dưới dạng một dấu thời gian duy nhất mặc dù nó hiện được biểu thị bằng thời gian POSIX. Cách chúng tôi xử lý các khoảng thời gian là yêu cầu khoảng thời gian của một giao dịch không bao gồm bất kỳ khoảng thời gian nào mà ngữ nghĩa phải lựa chọn. Ví dụ: nếu thời gian chờ là trưa ngày 3 tháng 1, giao dịch trong khoảng thời gian từ ngày 2 tháng 1 đến ngày 4 tháng 1 sẽ không thành công với `AmbiguousTimeInterval`. Người tham gia sẽ phải thực hiện một giao dịch trong khoảng thời gian từ ngày 2 tháng 1 đến một giây trước buổi trưa hoặc một giây từ trưa ngày 3 tháng 1 đến ngày 4 (hoặc cả hai).

Tuy nhiên, đối với Giá trị, chúng tôi cung cấp hai cấu trúc TimeIntervalStart và TimeIntervalEnd. Một giải pháp thay thế để xem xét sẽ là sửa đổi ngữ nghĩa để Giá trị không mang tính xác định, theo cách đó chúng ta có thể bao gồm cấu trúc CurrentTime và chỉ làm mất hiệu lực của các giao dịch không rõ ràng, nhưng điều này sẽ làm phức tạp ngữ nghĩa và làm cho chúng khó dự đoán hơn.

\[[1](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id1)] Chúng tôi có thể cung cấp một cách phân tích tĩnh hợp đồng để kiểm tra xem liệu có thể còn tiền trong bất kỳ tài khoản nào khi đến thời điểm Close hay không.

\[[2](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id2)] Điều này có nghĩa là các khoản thanh toán hiện tuân theo mô hình “đẩy” thay vì mô hình “kéo”.

\[[3](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id3)] Tuy nhiên, việc kích hoạt hợp đồng để xử lý thời gian chờ không phải là khẩn cấp `Notify`vì mặc dù `Observations`có thể xen kẽ giữa `True`và `False`, thời gian chờ chỉ có thể xảy ra một lần và, không phụ thuộc vào việc chúng đã được hợp đồng quan sát hay chưa, chúng không thể bị đảo ngược.

\[[4](https://marlowe-playground-staging.plutus.aws.iohkdev.io/doc/marlowe/tutorials/migrating.html#id4)] Thật vậy, một `Case`thời gian chờ không còn có thể được đưa ra sau thời gian chờ, ngay cả khi thời gian chờ đó không được hợp đồng quan sát, vì thời gian chờ được kiểm tra trước `Inputs`. Tuy nhiên, một người tham gia có thể muốn kích hoạt thời gian chờ trong trường hợp không `Inputs`cần người khác, ví dụ: để kích hoạt một hoặc nhiều khoản thanh toán. Trong việc triển khai ngữ nghĩa hiện tại sẽ được thực hiện bằng cách đưa ra một giao dịch với một danh sách trống `Inputs`.
