GVKun编程网logo

Bitcoin Computer——Token 合约(bitcoinwin合约交易)

1

对于BitcoinComputer——Token合约感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍bitcoinwin合约交易,并为您提供关于"message":"Unexpectedtoke

对于Bitcoin Computer——Token 合约感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍bitcoinwin合约交易,并为您提供关于"message": "Unexpected token < in JSON at position 0", "stack": "SyntaxError: Unexpected token < in JSON at position 0"、(Axios 拦截器) 从后台拿到 token 后存到 headers 中方法以及 token 过期报 401 的解决方法、Bitcoin Cash币值得长期持有吗?Bitcoin Cash币值得投资吗?、Bitcoin Cash币是什么币?Bitcoin Cash币有价值吗?的有用信息。

本文目录一览:

Bitcoin Computer——Token 合约(bitcoinwin合约交易)

Bitcoin Computer——Token 合约(bitcoinwin合约交易)

前面介绍了 Bitcoin Computer 的原理以及如何发送比特币。这次介绍 Token 方案。要理解本文,需要先阅读前两篇文章。

创建合约

先来看示例代码

import Computer from ''bitcoin-computer'';

class Token{
   
   
    constructor(supply, to) {
   
   
        this.tokens = supply;
        this._owners = [to];
    }

    send(amount, to){
   
   
        if(this.tokens < amount){
   
   
            throw new Error(`Not enough tokens: ${
     
     amount} < ${
     
     this.tokens}`);
        }

        this.tokens -= amount;
        return new Token(amount, to);
    }
}

(async () => {
   
   
    const computerA = new Computer.default({
   
   
        seed: ''seed of computer A'',
        chain: ''BSV'',
        network: ''testnet''
    });

    let tokens = await computerA.new(Token, [100, computerA.db.wallet.getPublicKey().toString()]);
    console.log(tokens);
})();
  1. 首先定一个了一个名为 Token 的智能合约。
    • 成员变量 tokens 表示 token 数量;成员变量_owners 表示这些数量的 token 属于谁。
    • 构造函数有两个参数,supply 表示该合约实例有多少个 token,to 是 token 拥有者的公钥。如果是首次创建合约,那么 supply 表示 token 总量是多少。
    • send 方法用于发送 token,amount 参数表示发送多少,to 参数是接收方的公钥。
  2. 创建 Computer 实例 computerA
  3. computerA 创建 Token 合约,总量 100,发放到自己的公钥里。

运行结果:

Token {
   
   
   tokens: 100,
       _owners: [
       ''03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f''
   ],
       _id: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0'',
       _rev: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0'',
       _rootId: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0''
}

可以在区块浏览器查看这笔转账,如果你读了前两篇文章,可以猜测出合约输出的内容,为了方便查看,我使用 ASM 格式的脚本,但把其中的可见字符串部分直接用 UTF8 格式表示:

1
03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f
1
OP_CHECKMULTISIG

{"__cls":"class Token{\n constructor(supply, to) {\n this.tokens = supply;\n this._owners = [to];\n }\n\n send(amount, to){\n if(this.tokens < amount){\n throw new Error(`Not enough tokens: ${amount} < ${this.tokens}`);\n }\n\n this.tokens -= amount;\n return new Token(amount, to);\n }\n}","__index":{"obj":0},"__args":[100,"03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f"],"__func":"constructor"}

OP_DROP

多签名的公钥为 ComputerA 的公钥。合约数据部分为 Token 类的定义,以及构造函数名称及运行参数,表示用构造函数和参数创建了一个合约实例。

token 转账

const computerB = new Computer.default({
   
   
        seed: ''seed of computer B'',
        chain: ''BSV'',
        network: ''testnet''
    });
await tokens.send(10, computerB.db.wallet.getPublicKey().toString());
    console.log(tokens);
  1. 创建另一个 Computer 实例 computerB
  2. computerA 把 10 个 token 转给 computerB

运行结果:

Token {
   
   
    tokens: 90,
        _owners: [
        ''03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f''
    ],
        _id: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0'',
        _rev: ''171c0c8713b8c8a97c556b286c95b821e0ff64170b681c946d4123aee9134e79:0'',
        _rootId: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0''
}

可以看到,转账结束后,computerA 的 token 数量还剩下 90。

通过区块链浏览器查看这个 tx,输出结构上跟以往的例子有些不一样。以往的合约都有两个输出,一个合约输出,一个找零输出。而这个 token 转账 tx 有三个输出,其中第三个是找零。接下来详细看看前两个输出。

输出 0

1
03367b59cc6ba5cdb93b3bdc61c7018655462251b3608383c5a1b4adcf5f1bcc1f
1
OP_CHECKMULTISIG

{"__index":{"obj":0,"res":1},"__args":[10,"02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90"],"__func":"send"}

OP_DROP

很明显这是一个合约运行输出脚本,多签名的公钥是 computerA 的,数据部分是合约运行的函数和参数。
跟以往例子不同的是,合约数据中的__index 字段里多了一个 res 字段,值为 1。因为开发者并没有公布协议,所以并不能准确知道这个字段的含义,我猜测这里的 1 表示输出 1:这个合约的运行给输出 1 提供了一些必要信息。

输出 1

1
02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90
1
OP_CHECKMULTISIG

{"__cls":"class Token{\n constructor(supply, to) {\n this.tokens = supply;\n this._owners = [to];\n }\n\n send(amount, to){\n if(this.tokens < amount){\n throw new Error(`Not enough tokens: ${amount} < ${this.tokens}`);\n }\n\n this.tokens -= amount;\n return new Token(amount, to);\n }\n}"}

OP_DROP

这个输出的多签名公约是 computerB 的,所以应该表示一部分 token 转到了 computerB 名下。合约数据部分是一份 Token 类的定义。

到这里,需要再看看 Token 类中 send 方法的实现。其中真正的转账代码是通过再创建一个 Token 类实例来实现的,构造函数的参数就是发送数量接收者公钥。所以,我猜测,合约代码中这行代码的逻辑体现在 tx 中就是这个输出。

同时,合约数据中并没有出现合约创建 tx 输出中的__args__func 字段,__args 字段应该是来自输出 0 中的__args,这也就是我们前面说到的输出 0 给输出 1 提供了必要信息。

computerB 的视角

前面我们用 computerA 的 token 实例转完账后,token 数量还剩 90。接下来我们用 compuerB 把转账 tx 同步下来,用它的视角来看看 token 的数量。
因为输出 1 才是属于 computerB 的,所以首先先把版本号的 outputIndex 部分改为 1,然后再进行同步。

const computerBTokenRev = tokens._rev.split('':'')[0]+'':1'';

tokens = await computerB.sync(computerBTokenRev);
console.log(tokens);

运行后 tokens 变量的值为:

Token {
    tokens: 10,
        _owners: [
        ''02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90''
    ],
        _rev: ''171c0c8713b8c8a97c556b286c95b821e0ff64170b681c946d4123aee9134e79:1'',
        _id: ''171c0c8713b8c8a97c556b286c95b821e0ff64170b681c946d4123aee9134e79:1'',
        _rootId: ''37e47c71219a0f7f3b80c04b24bbfa4613364cb1a81a9b166a33178c375ba628:0''
}

属于 computerB 的 token 数量为 10,跟预期一致。
同时还发现一个有意思的现象:_id 字段不再是合约部署的 outPoint,而是转账 tx 的输出 1。而_rootId 字段仍然是合约部署的 outPoint。因此,我猜测_rootId 表示部署合约的 outPoint,_id 表示当前合约实例开始创建的 outPoint(属于 compuerB 的合约实例在部署时还没有,在 compuerA 转账后才出现)。

安全性

上链前保护

Token 方案的首要安全性是对 token 数量的计算是否正确。我们沿用上面的程序继续对安全性进行测试。

tokens = await computerA.sync(''171c0c8713b8c8a97c556b286c95b821e0ff64170b681c946d4123aee9134e79:0'');
tokens.send(91, computerB.db.wallet.getPrivateKey().toString());
  1. computerA 把它的合约 UTXO 同步下来,此时还剩 90 个 token。
  2. 尝试给 computerB 转出 91 个 token。

运行时抛出了一个异常:

UnhandledPromiseRejectionWarning: Error: Not enough tokens: 91 < 90

仔细看 send 函数的实现,最开始就是对 token 数量的保护,如果实例没有那么多 token,就抛出了异常,并跳出了 send 函数的运行。也就是说会发送失败,从而在上链前就保证了 token 数量的正确。
所以,Bitcoin Computer 用 Javascript 的异常功能巧妙地对合约的安全性进行了保护。

上链后保护

如果手工构造一笔不合法的转账,是否可以突破 token 数量的异常保护呢?我构造了一笔转账,标记 computerAcomputerB 转了 91 个 token,实际上 computerA 只有 90 个。

{
  "__index":{"obj":0,"res":1},
  "__args":[91,"02c9788a60264523ba77500e19a0b2626c9b09b25daa16cfee09b4e1135d610c90"],
  "__func":"send"
}

对于已经在链上的非法转账,我们看 Bitcoin Computer 会如何表现:

const tokens = await computerA.sync(''51bdee16d6b452aec909908c228c355ab7ca7bc311952ce7897d5e9bfa2fcb3d:0'');
console.log(tokens);

computerA 从记载非法转账记录的 outPoint 加载合约数据,运行程序,抛出了如下异常:

UnhandledPromiseRejectionWarning: Error: Not enough tokens: 91 < 90

再来看看 computerB 加载非法转账会如何表现:

const tokens = await computerB.sync(''51bdee16d6b452aec909908c228c355ab7ca7bc311952ce7897d5e9bfa2fcb3d:1'');
console.log(tokens);

代码运行时仍然抛出了异常:

UnhandledPromiseRejectionWarning: Error: Not enough tokens: 91 < 90

综上,虽然不合法的合约数据可以手动写入链上,但在运行 Javascript 合约代码时,合约可以检查出逻辑错误,并抛出异常,程序停止运行。

总结

Bitcoin Computer 的 Token 合约虽然简短,但实现上比较精巧:

  1. 通过创建新的合约实例实现转账。
  2. 直接用 Javascript 代码对 token 数量进行保护。

后记

写完了三篇关于 Bitcoin Computer 的介绍文章,这个系列就暂告一断落了。

由于 Bitcoin Computer 的协议并没有公开,我只是凭经验和测试来猜测 Bitcoin Computer 的运行原理,细节不一定准确,欢迎大家一起交流。同时也希望开发者可以尽快公布协议,对于二层合约方案来说,协议的公开性是必须的,否则无法满足用户的安全需求。

另外,有一个原理类似的二层合约方案 Run,该方案只运行在 BSV 链,RelayX 基于该方案发布了 USDC Token。最初我是想介绍这个方案的,但由于该方案没有公开代码和文档,所以选择了 Bitcoin Computer。希望 Run 也可以尽快公布自己的协议、文档和代码。

"message": "Unexpected token < in JSON at position 0", "stack": "SyntaxError: Unexpected token < in JSON at position 0"

如何解决"message": "Unexpected token < in JSON at position 0", "stack": "SyntaxError: Unexpected token < in JSON at position 0"

const express = require(''express'');
const {graphqlHTTP} = require(''express-graphql'');
const schema = require(''./schema/schema'');

const app = express();

app.get(''/graphql'',graphqlHTTP({
    graphiql:true,schema: schema
}))

app.listen(4000,()=>{
    console.log("listining to port 4000..")
}) 

const graphql = require(''graphql'');

const{
    GraphQLObjectType,GraphQLID,GraphQLString,GraphQLInt,GraphQLSchema
} = graphql

const UserType = new GraphQLObjectType({
    name: ''user'',description: ''Documentation for User...'',fields: ()=>({
        id: {type: GraphQLString},name: {type: GraphQLString},age: {type: GraphQLInt}
    })
});

const RootQuery = new GraphQLObjectType({
    name: ''RootQueryType'',description: ''description'',fields: {
        user: {
            type: UserType,args: {id: {type: GraphQLString}},resolve(parent,args){
                let user = {
                    id: ''345'',age: 34,name: ''Aman''
                }
                return user;
            }      
        }
    }
});

module.exports = new GraphQLSchema({
    query: RootQuery
})

以上是我的代码,我收到此错误:

"message": "位置 0 处的 JSON 中的意外标记 "stack": "SyntaxError: Unexpected token

谁能告诉我我是如何解决这个错误的?提前致谢。

解决方法

这似乎是您在客户端应用程序中看到的错误?附带说明一下,您没有添加很多细节,说明您正在做什么以获取此错误,您在哪里看到它,以及您认为导致它的原因,所以我只能离开您提供的内容就您的设置而言。

这似乎是您从您期望 JSON 的服务器收到 HTML 响应。通常,使用 GraphQL 可能会发生这种情况,因为您发送的是 GET 请求(这可能会启动 GraphiQL 资源管理器)而不是 POST 请求。

您的 GraphQL 客户端代码应该发出一个 POST 请求,并且您应该确保它发送一个标头来接受 Duration 响应。

(Axios 拦截器) 从后台拿到 token 后存到 headers 中方法以及 token 过期报 401 的解决方法

(Axios 拦截器) 从后台拿到 token 后存到 headers 中方法以及 token 过期报 401 的解决方法

我自己根据 method 是 GET 还是 POST 请求分开定义了两个 axios

let myPost = axios.create({
   
   //POST请求
    baseURL: urls.baseUrl,
    method: ''post'',
})
let myGet = axios.create({
   
   //GET请求
    baseURL: urls.baseUrl,
    method: ''get'',
})

请求拦截器(请求之前的操作)

myPost.interceptors.request.use(config => {
   
   
    if (sessionStorage.getItem("token")) {
   
   //在这里获取到登录成功后存的token,并加到headers中
        config.headers.token = sessionStorage.token
    }
    console.log(config)
    return config;
}, error => {
   
   
    console.log(error);
    return Promise.reject();
})
myGet.interceptors.request.use(config => {
   
   
    if (sessionStorage.getItem("token")) {
   
   
        config.headers.token = sessionStorage.token
    }
    console.log(config)
    return config;
}, error => {
   
   
    console.log(error);
    return Promise.reject();
})

响应拦截器(请求后的操作)

myPost.interceptors.response.use(response => {
   
   
    if (response.status === 200) {
   
   
        return response;
    } else {
   
   
        Promise.reject();
    }
}, error => {
   
   
    //错误跳转(这里只是根据我自己的项目做得操作【这里你们根据自己的项目来判断错误时的处理】)
    if (error.response.status === 500) {
   
   
        console.log(error.response.data.info)
    } else if (error.response.status === 401) {
   
   
        sessionStorage.setItem("isLogin", false);
        console.log(sessionStorage.getItem("isLogin"));
        router.push({
   
    path: "/" })
        router.go(0)
        return Promise.reject();
    }
})
myGet.interceptors.response.use(response => {
   
   
    if (response.status === 200) {
   
   
        return response;
    } else {
   
   
        Promise.reject();
    }
}, error => {
   
   
    //错误跳转
    if (error.response.status === 500) {
   
   
        console.log(error.response.data.info)
    } else if (error.response.status === 401) {
   
   
        sessionStorage.setItem("isLogin", false);
        console.log(sessionStorage.getItem("isLogin"));
        router.push({
   
    path: "/" })
        router.go(0)
        return Promise.reject();
    }
})

Bitcoin Cash币值得长期持有吗?Bitcoin Cash币值得投资吗?

Bitcoin Cash币值得长期持有吗?Bitcoin Cash币值得投资吗?

bitcoin cash币值得长期持有吗?bitcoin cash币值得投资吗?

Bitcoin Cash(BCH)具有长期持有价值,但需考虑市场波动、监管风险和竞争风险。其技术优势、社区支持、商业应用和市场认可度使其具有长期发展前景。投资者应谨慎投资,进行风险分散,并做好长期持有的准备。

Bitcoin Cash币值得长期持有吗?

Bitcoin Cash币(BCH)是一种加密货币,于2017年8月1日通过比特币硬分叉诞生。BCH旨在解决比特币区块大小限制的问题,从而提高交易速度和降低交易费用。

BCH的风险及影响因素:

  • 市场波动风险:加密货币市场波动很大,BCH的价格也受到市场情绪的影响。在牛市中,BCH的价格可能会大幅上涨,但在熊市中,BCH的价格可能会大幅下跌。
  • 监管风险:各国政府对加密货币的态度不尽相同,一些国家可能会对加密货币进行监管,甚至禁止交易。如果BCH受到监管,可能会影响其价格和发展。
  • 竞争风险:BCH面临着来自其他加密货币(如比特币、以太坊)的竞争。如果这些竞争对手的技术或生态系统更具优势,可能会影响BCH的长期发展。

BCH的发展前景:

  • 技术优势:BCH具有较大的区块大小,可以处理更多的交易,从而提高交易速度和降低交易费用。这使其在支付场景中具有优势。
  • 社区支持:BCH拥有一个活跃的社区,包括开发人员、矿工和用户。社区的支持有利于BCH的长期发展。
  • 商业应用:一些商家开始接受BCH支付,这将扩大BCH的使用场景,有利于BCH的长期发展。

BCH的市场认可度:

BCH是目前市值排名靠前的加密货币之一,在全球范围内拥有大量的投资者和用户。BCH的市场认可度正在不断提高,这有利于其长期发展。

结论:

BCH是一种具有风险和潜力的加密货币。投资者在投资BCH之前,需要充分了解其风险和影响因素,并进行风险评估。

投资建议:

  • 不要将所有资金都投资于BCH,要进行风险分散。
  • 不要追涨杀跌,要理性投资。
  • 做好长期持有的心理准备。

以上就是Bitcoin Cash币值得长期持有吗?Bitcoin Cash币值得投资吗?的详细内容,更多请关注php中文网其它相关文章!

Bitcoin Cash币是什么币?Bitcoin Cash币有价值吗?

Bitcoin Cash币是什么币?Bitcoin Cash币有价值吗?

bitcoin cash币是什么币?bitcoin cash币有价值吗?

Bitcoin Cash:一种有价值的加密货币

Bitcoin Cash (BCH) 是一种加密货币,于 2017 年从比特币 (BTC) 硬分叉而来。其目的是解决比特币区块链上的可扩展性问题。

Bitcoin Cash 的特点

  • 更大的区块大小:BCH 的区块大小为 32MB,是 BTC 区块大小的 8 倍。这允许更多的交易在每个区块中处理,从而提高可扩展性。
  • 更快的确认时间:由于更大的区块大小,BCH 的确认时间通常比 BTC 更快。
  • 较低的交易费用:BCH 的交易费用通常低于 BTC,尤其是在网络拥堵时。

Bitcoin Cash 的用途

BCH 可用于以下用途:

  • 支付:BCH 可用于在线和实体店购买商品和服务。
  • 汇款:BCH 可用于快速且低成本地向世界各地汇款。
  • 投资:BCH 是一种投资工具,其价值可能会随着时间的推移而波动。

Bitcoin Cash 的价值

BCH 的价值取决于多种因素,包括:

  • 网络使用:BCH 的使用量越大,其价值就越高。
  • 市场需求:如果对 BCH 的需求很高,其价值就会上涨。
  • 竞争:来自其他加密货币的竞争可能会影响 BCH 的价值。

结论

Bitcoin Cash 是一种有价值的加密货币,具有更大的区块大小、更快的确认时间和较低的交易费用。它可用于支付、汇款和投资。虽然其价值可能会波动,但 BCH 的长期前景仍然光明。

以上就是Bitcoin Cash币是什么币?Bitcoin Cash币有价值吗?的详细内容,更多请关注php中文网其它相关文章!

今天关于Bitcoin Computer——Token 合约bitcoinwin合约交易的介绍到此结束,谢谢您的阅读,有关"message": "Unexpected token < in JSON at position 0", "stack": "SyntaxError: Unexpected token < in JSON at position 0"、(Axios 拦截器) 从后台拿到 token 后存到 headers 中方法以及 token 过期报 401 的解决方法、Bitcoin Cash币值得长期持有吗?Bitcoin Cash币值得投资吗?、Bitcoin Cash币是什么币?Bitcoin Cash币有价值吗?等更多相关知识的信息可以在本站进行查询。

本文标签:

上一篇Computer Systems A Programmer''s Perspective

下一篇[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理(phong光照明模型公式)