동적 필드 마이그레이션 가이드

동적 필드는 Sui Move 의 새로운 개념으로, 자식 객체를 대체하고 프로그래밍 유연성을 향상시킵니다.

동적 필드 마이그레이션 가이드

출시와 함께 Sui 0.13.0에서 자식 객체의 개념을 동적 필드로 대체할 것입니다. 이것은 획기적인 변화에서 자식 객체와 상호 작용하기 위한 Move API를 사용하여 sui::전송 (전송_투_객체 그리고 전송_투_객체_ID)가 제거되고 다음으로 대체됩니다. sui::동적_필드 그리고 sui::동적_객체_필드 를 사용하여 동적 필드로 작업할 수 있습니다.

자식 객체를 사용하는 애플리케이션에서 오류를 방지하려면 아래의 마이그레이션 가이드를 따르고 Devnet이 0.13.0으로 업데이트될 때 변경 사항을 적용할 준비를 하시기 바랍니다( #devnet-updates 를 참조하세요). 애플리케이션의 다운타임을 최소화하려면 동적 필드와 상호 작용하기 위한 새로운 API를 사용할 수 없으므로 Devnet 업데이트가 끝날 때까지 변경 사항을 적용하지 마시기 바랍니다.

동적 필드란 무엇인가요?

동적 필드는 자식 객체의 일반화입니다. 이를 통해 Sui 의 Move 개발자는 새로운 데이터로 구조를 즉시 확장할 수 있습니다.

그들 자식 객체에 대한 주요 불만 사항 해결 를 통해 조상 소유권 체인(부모, 부모의 부모 등)을 발신자가 소유한 루트 객체까지 전달해야 합니다. 항목 함수를 사용할 수 없습니다. 이 제한으로 인해 깊게 중첩된 자식 객체로 작업하는 데 어려움이 있었고, 트랜잭션 시작 시 조상 체인을 알 수 없는 경우(예: 자식 객체를 동적으로 로드하는 경우)에는 지원되지 않았습니다. 동적 필드를 사용하면 루트 객체만 항목 함수를 사용할 수 있으며, 트랜잭션 실행 중에 동적 필드에 즉시 액세스할 수 있습니다. (실제로 동적 필드 값을 입력 함수에 입력으로 전달하면 이제 실패합니다).

몇 가지 다른 개선 사항도 함께 제공됩니다:

  • 어떤 store 값으로 변환할 수 있습니다.
  • 이름으로 필드에 레이블 지정 및 조회(여기서 이름은 어떤 이름이라도 가능합니다. 복사, drop, store 값).
  • 다음과 같은 새로운 온체인 키-값 저장소를 지원합니다. (동종 키 및 값) 및 가방 (이기종 키 및 값).

그들과 함께 미쳐보세요! 데이터 구조가 없어서 Move 에서 구현할 수 없다는 불만을 많이 들었습니다. 이제 Move 에서 모든 종류의 데이터 구조를 효율적으로 구현할 수 있을 것입니다! 링크된 해시맵이든 접두사 트리든 단순한 링크된 목록이든 상관없습니다. 동적 필드를 사용하려면 스토리지에 객체를 읽고 써야 합니다. 하지만 아주 적은 수의 항목에 대해서는 복잡한 데이터 구조보다 간단한 벡터가 더 효율적일 것으로 예상됩니다.

전류 제한

아직 다이나믹 필드의 일부 기능을 개발 중이지만, 이 기능을 통해 무엇을 만들 수 있는지 확인하고 피드백을 받고자 이 기능을 여러분과 공유하고 싶었습니다. 이 기능을 사용하는 동안 다음과 같은 알려진 문제에 주의하시기 바라며, 이는 향후 릴리스에서 해결될 예정입니다:

  • 제거 는 현재 최적화되지 않았으며 전체 스토리지 환불을 제공하지 않습니다. 내부적으로는 dynamic_field (그리고 동적_객체_필드) 생성 필드 객체를 사용하여 키-값 쌍을 저장합니다.
  • 현재 exists_ 함수 dynamic_field를 사용하여 지정된 이름의 필드가 객체에 이미 정의되어 있는지 확인합니다.
  • 동적 필드 객체에는 몇 가지 잠재적인 내구성/일관성 문제가 있습니다: 동적 필드가 있는 트랜잭션을 처리하는 동안 유효성 검사기가 다운되었다가 다시 올라오면 해당 개체가 있는 트랜잭션을 더 이상 처리하지 못할 수 있습니다. 현재 이 문제를 해결하기 위해 적극적으로 노력하고 있습니다.

마이그레이션 가이드

아래 제안 사항은 기존의 자식 객체 사용을 동적 필드 사용으로 전환하는 데 효과적이지만, 많은 경우 API 사용법을 재고해야 할 수도 있다는 점에 유의하세요. 많은 경우 코드를 더 단순하게 만들거나 최종 사용자에게 더 친숙하게 만들 수 있습니다. 아래 예제는 드롭인 대체를 통해 작업을 실행하는 데 도움이 되도록 설계되었습니다.

통화를 다음으로 바꾸기 전송_투_객체 와 함께 추가

// Old, Child Object API 
use sui::transfer; 
transfer::transfer_to_object(&mut parent, child) 

// New, Dynamic Field API 
use sui::dynamic_object_field as ofield; 
let id = object::id(&child); 
ofield::add(&mut parent.id, id, child);

새 API는 다음에 필드를 추가합니다. 부모 와 함께 child의 ID를 이름으로 지정하고 child 를 값으로 입력합니다.

소유권 조상 체인을 다음에서 교체합니다. 항목 통화를 통한 즐거움 빌리기, borrow_mut또는 제거

(참고: 이 제안은 이전 제안에 따라 다음에서 마이그레이션했다고 가정합니다. 전송_투_객체OFFIELD::ADD 를 사용하여 child의 ID를 필드 이름으로 사용합니다).

// Child, Parent, GrandParent are all Objects
struct Child       has key, store { id: UID, /* ... */ }
struct Parent      has key, store { id: UID, /* ... */ }
struct GrandParent has key, store { id: UID, /* ... */ }

// Old, Child Object API
entry fun read_child(gp: &GrandParent, p: &Parent, c: &Child) {
    /* ... */
}
entry fun write_child(gp: &mut GrandParent, p: &mut Parent, c: &mut Child) {
    /* ... */
}

entry fun take_child(gp: &mut GrandParent, p: &mut Parent, c: Child) {
    /* ... */
}

// New, Dynamic Field API
use sui::dynamic_object_field as ofield;

entry fun read_child(gp: &GrandParent, pid: ID, cid: ID) {
    let p = ofield::borrow<ID, Parent>(&gp.id, pid);
    let c = ofield::borrow<ID, Child>(&p.id, cid);
    /* ... */
}

entry fun write_child(gp: &mut GrandParent, pid: ID, cid: ID) {
    let p = ofield::borrow_mut<ID, Parent>(&mut gp.id, pid);
    let c = ofield::borrow_mut<ID, Child>(&mut p.id, cid);
    /* ... */
}

entry fun take_child(gp: &mut GrandParent, pid: ID, cid: ID) {
    let p = ofield::borrow_mut<ID, Parent>(&mut gp.id, pid);
    let c = ofield::remove<ID, Child>(&mut p.id, cid);
    /* ... */
}

동적 필드에 대해 자세히 알아보기